DB2 锁问题分析与解释





DB2 应用中常常会遇到锁超时与死锁现象,那么这样的现象产生的原因是什么呢。本文以试验的形式模拟锁等待、锁超时、死锁现象。并给出这些现象的根本原因。

试验环境:





DB2 v9.7.0.6

AIX 6.1.0.0

採用默认的隔离级别CS



STUDENT表的DDL与初始内容

------------------------------------------------

-- DDL Statements for table "E97Q6C  "."STUDENT"

------------------------------------------------

 

CREATE TABLE "E97Q6C  "."STUDENT"  (

                  "AGE" INTEGER , 

                  "NAME" CHAR(8) )   

                 IN "USERSPACE1" ; 





$ db2 "select * from student"





AGE         NAME    

----------- --------

          3 xu      

          5 gao     

          2 liu     

          1 gu      















试验1:验证insert操作与其它操作的锁等待问题





session 1中发出insert操作,在session 2中观察insert,update,delete操作是否会锁超时。

session 1

---------

$ db2 +c "insert into student values(4, 'miao')"

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 "insert into student values(6, 'mu')"

DB20000I  The SQL command completed successfully.

$ db2 "update student set name='gu' where age=1"

DB20000I  The SQL command completed successfully.

$ db2 "delete from student where age=2"

DB20000I  The SQL command completed successfully.

----------------------------------------------------------------------------

结论1:当session 1对表作insert操作时,session 2对该表的insert及其它行的update,delete操作都不会有问题





----------------------------------------------------------------------------





试验2:验证update操作与其它操作的锁等待问题

session 1中发出update操作,在session 2中观察insert,update,delete操作是否会锁超时。

--------------

session 1

---------

$ db2 commit





$ db2 "select * from student"





AGE         NAME    

----------- --------

          3 xu      

          5 gao     

          6 mu      

          4 miao    

          1 gu      





  5 record(s) selected.





$ db2 +c "update student set name = 'qing' where age=4"

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 "insert into student values(6, 'mu')"

DB20000I  The SQL command completed successfully.

$ db2 "update student set name='gu' where age=1"

DB21034E  The command was processed as an SQL statement because it was not a 

valid Command Line Processor command.  During SQL processing it returned:

SQL0911N  The current transaction has been rolled back because of a deadlock 

or timeout.  Reason code "68".  SQLSTATE=40001

$ db2 "delete from student where age=2"

DB21034E  The command was processed as an SQL statement because it was not a 

valid Command Line Processor command.  During SQL processing it returned:

SQL0911N  The current transaction has been rolled back because of a deadlock 

or timeout.  Reason code "68".  SQLSTATE=40001





----------------------------------------------------------------------------

结论2:当session 1对表某一行做update操作时,session 2能够对该表作insert操作,但不同意对其它行的delete和update操作

----------------------------------------------------------------------------

试验3:验证delete操作与其它操作的锁等待问题

session 1中发出delete操作,在session 2中观察insert,update,delete操作是否会锁超时。

Session 1

---------

$ db2 commit





$ db2 +c "delete from student where age=4"

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 "insert into student values(6, 'mu')"

DB20000I  The SQL command completed successfully.





$ db2 "update student set name='gu' where age=1"

DB21034E  The command was processed as an SQL statement because it was not a 

valid Command Line Processor command.  During SQL processing it returned:

SQL0911N  The current transaction has been rolled back because of a deadlock 

or timeout.  Reason code "68".  SQLSTATE=40001





$ db2 "delete from student where age=2"

DB21034E  The command was processed as an SQL statement because it was not a 

valid Command Line Processor command.  During SQL processing it returned:

SQL0911N  The current transaction has been rolled back because of a deadlock 

or timeout.  Reason code "68".  SQLSTATE=40001

----------------------------------------------------------------------------

结论3:当应用1对表某一行做delete操作时,应用2能够对该表作insert操作。但不同意对其它行的delete和update操作

----------------------------------------------------------------------------





总的结论是:

应用对表作insert操作时。其它操作不受影响,也不受其它操作影响。

作update,delete操作时,其它的update和delete操作受影响。





为了解释以上现象的原因,我们首先看一下上面的操作须要什么样的锁。





session 1.

---------

$ db2 rollback





$ db2 +c "insert into student values(7,'han')"

DB20000I  The SQL command completed successfully.

$ db2pd -db qsmiao -locks

结论:insert操作须要表级的IX锁和行级的X锁。

注:IX锁。该锁的拥有者在拥有对应行的X锁时能够更改该行的数据。





$ db2 rollback





$ db2 +c "update student set name='yan' where age=5"

DB20000I  The SQL command completed successfully.





$ db2pd -db qsmiao -locks



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWluZ3NvbmczMzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">





结论:update操作须要表级的IX锁和行级的X锁。





$ db2 rollback





$ db2 +c "delete from student where age=6"

DB20000I  The SQL command completed successfully.

$ db2pd -db qsmiao -locks

结论:update操作须要表级的IX锁和相应的行级的X锁(这里由于3条记录的age都为6,因此须要3个行级锁)。





如今的问题是:为什么insert和update,delete操作须要的锁一样(表级的IX锁。相应行级的X锁),可是表现的效果却不一样呢?





为了解决问题。看一下他们的运行计划吧:





$ db2expln -d qsmiao -g -statement "insert into student values(5, 'gao')" -terminal



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWluZ3NvbmczMzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">



$ db2expln -d qsmiao -g -statement "update student set name='qing' where age=4" -terminal











$ db2expln -d qsmiao -g -statement "delete from student where age=6" -terminal









从上面的运行计划中能够看到原因:insert操作不须要表扫描,而update和delete操作都须要全表扫描,并且会在扫描的时候试图对每一行加U锁。

导致锁超时的原因就是表扫描

比如session 1要更新表的某一行,会在该行加上X锁。之后, session 2试图更新该表的还有一行,进行全表扫描时,就会试图对A占用的那一行加上U锁,但无能为力,终于导

致锁超时。

为了验证该说法,能够抓取锁等待的消息。





session 1

---------

$ db2 +c "update student set name='hehe' where age = 4"

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 +c "delete from student where age=6"

       <-------这时会hang住。由于它在等session 1的锁





session 3

---------

$ db2pd -db qsmiao -wlocks  <---在锁超时发生之前,抓取锁等待的消息



Locks being waited on :

AppHandl [nod-index] TranHdl    Lockname                                   Type       Mode Conv Sts      CoorEDU  AppName  AuthID   AppID                           

15393    [000-15393] 2               00020004000000000000000952
Row        ..X       G    7818       db2bp    E97Q6C   *LOCAL.e97q6c.141016035113       

15408    [000-15408] 16             00020004000000000000000952
Row        ..U       W   10153      db2bp    E97Q6C   *LOCAL.e97q6c.141016035219     





能够看到,是由于U锁和X锁的不兼容导致锁等待,最后导致锁超时。







为了解决该锁等待问题,能够在查询谓词所涉及的列age上建立索引,避免全表扫描





试验4:通过建立索引,消除锁等待现象





session 1

---------

$ db2 rollback





$ db2 +c "lock table student in share mode"





$ db2 +c "create index stu_idx on student(age)"





$ db2 commit





$ db2 +c "update student set name='hehe' where age = 4"

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 +c "delete from student where age=6"  <--没有发生锁等待现象,直接成功

DB20000I  The SQL command completed successfully.





能够看到,已经通过索引攻克了该锁超时问题。假设读者有兴趣的话,能够看下建立索引之后的訪问计划。













以下模拟一个死锁现象

试验5:模拟死锁,步骤例如以下

第一步:session 1 获得 锁 LOCK1





第二步:session 2 获得 锁 LOCK2





第三步:session 2 申请 锁 LOCK1





第四步:session 1 申请 锁 LOCK2





为了避免死锁之前产生锁超时,先将锁超时控制參数设为-1(表示永远等待)

update db cfg using locktimeout -1

之后重新启动数据库





session 1

---------

$ db2 +c "update student set name = 'an' where age = 1"       <--获得锁LOCK1,成功

DB20000I  The SQL command completed successfully.





session 2

---------

$ db2 +c "update student set name = 'two' where age = 4"      <--获得锁LOCK2,成功

DB20000I  The SQL command completed successfully.





$ db2 +c "update student set name = 'four' where age = 1"     <--申请锁LOCK1,hang住。由于LOCK1被session 1持有





session 1

---------

$ db2 +c "update student set name = 'three' where age = 4"    <--申请锁LOCK2,hang住,由于LOCK2被session 2持有









这时已经发生了死锁,10s之后,这两个session有一个会报出例如以下死锁(reason code 2)错误。还有一个session成功运行

SQL0911N  The current transaction has been rolled back because of a deadlock 

or timeout.  Reason code "2".  SQLSTATE=40001





參考资料:

标准表的锁定方式和存取方案,这里您能够看到具体的加锁方式

http://www-01.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.admin.perf.doc/doc/r0005275.html?lang=zh





附。仅仅能在发生死锁或者锁等待的时候才干用db2pd查看锁的信息。以下附上怎样採用事件监控器监控死锁/锁超时。事件监控器能够抓取一段时间内的锁事件

db2 update db cfg for sample using MON_LOCKWAIT hist_and_values MON_DEADLOCK hist_and_values MON_LOCKTIMEOUT hist_and_values MON_LW_THRESH 10000

db2 "CREATE EVENT MONITOR LOCKEVMON FOR LOCKING WRITE TO UNFORMATTED EVENT TABLE (TABLE LOCKEVMON)"

db2 set event monitor LOCKEVMON state=1





重现问题





db2 flush event monitor LOCKEVMON

db2 set event monitor LOCKEVMON state=0





cp /home/db2users/e97q6c/sqllib/samples/java/jdbc/db2evmonfmt.java ./

cp /home/db2users/e97q6c/sqllib/samples/java/jdbc/DB2EvmonLocking.xsl ./

export PATH=/home/db2users/e97q6c/sqllib/java/jdk64/bin:$PATH





javac db2evmonfmt.java





java db2evmonfmt -d sample -ue LOCKEVMON -ftext -u e97q6c -p e97q6c > deadlock.txt

more deadlock.txt 能够看到有关的SQL语句。

请參考

http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1004lockeventmonitor/

http://blog.csdn.net/qingsong3333/article/details/51206329

DB2 锁问题分析与解释的更多相关文章

  1. linux RCU锁机制分析

    openVswitch(OVS)源代码之linux RCU锁机制分析 分类: linux内核  |  标签: 云计算,openVswitch,linux内核,RCU锁机制  |  作者: yuzhih ...

  2. DB2锁机制

    相比较Oracle来说,DB2的锁机制麻烦了很多,而且这个麻烦带来的不是性能的上升而是下降,不过如果细致了解的话,只能感慨不愧是数据库理论诞生的公司,在实现数据库理论上比Oracle全面得多.    ...

  3. SQL Server中CURD语句的锁流程分析

    我只在数据库选项已开启“行版本控制的已提交读”(READ_COMMITTED_SNAPSHOT为ON)中进行了观察. 因此只适用于这种环境的数据库. 该类数据库支持四种不同事务隔离级别,下面分别观察数 ...

  4. MySQL锁等待分析【2】

    MySQL锁等待分析[1]中对锁等待的分析是一步一步来的.虽然最后是分析出来了,可是用时是比较长的:理清各个表之间的关系后,得到如下SQL语句,方便以后使用 select block_trx.trx_ ...

  5. ElasticSearch评分分析 explian 解释和一些查询理解

    ElasticSearch评分分析 explian 解释和一些查询理解 按照es-ik分析器安装了ik分词器.创建索引:PUT /index_ik_test.索引包含2个字段:content和nick ...

  6. DB2锁表或超时解决方案

    DB2锁表或超时 一.场景 对数据表进行更新(查询没问题),错误提示如下: SQLCODE=-911, SQLSTATE=40001, DRIVER=3.63.75SQL0911N The curre ...

  7. Java多线程——线程八锁案例分析

    Java多线程——线程八锁案例分析 摘要:本文主要学习了多线程并发中的一些案例. 部分内容来自以下博客: https://blog.csdn.net/dyt443733328/article/deta ...

  8. 图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析

    图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据 ...

  9. Redisson 实现分布式锁原理分析

    Redisson 实现分布式锁原理分析   写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题.​ 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有 ...

随机推荐

  1. Objective-C类族和工厂模式

    http://www.cocoachina.com/ios/20141124/10296.html 相信大家都了解GoF的<Design Patterns>中提到的23种设计模式,其中将常 ...

  2. popen的用法及与system调用的区别

    首先用man查看下popen的介绍: popen(3) - Linux man page Name popen, pclose - pipe stream to or from a process S ...

  3. 用css控制table td内文字超出隐藏

    (如有错敬请指点,以下是我工作中遇到并且解决的问题) 效果图: 重点是把table设置为table-layout: fixed; 超出的文字隐藏的效果才有. p标签超出的文字隐藏的效果不需要设置这个内 ...

  4. python 查询数据

    查找课程不及格学生最多的前5名老师的id 表:student 字段名 类型 是否为空 主键 描述 StdID int 否 是 学生ID StdName varchar(100) 否 学生姓名 Gend ...

  5. OutputDebugString方便格式化WIN32封装

    void TRACE(LPCTSTR lpszFmt, ...) { va_list args; va_start(args, lpszFmt); ; TCHAR *lpszBuf = (TCHAR* ...

  6. 使用navicat连接linux服务器数据库方法

    主机名用localhost 要使用SSH连接

  7. MVC5 WebAPI 跨域处理

    问题描述: 在使用ASP.NET的MVC5进行WebAPI开发的时候,在跨域的情况下会报跨域的错, No 'Access-Control-Allow-Origin' header is present ...

  8. 集合框架(01)Collection

    1.集合:存储对象. 对象多了用集合存,数据多了用对象存 2.数组是固定长度,集合是不固定长度:数组是相同数据类型,集合是存储不同类型的对象 3 . 4.为什么会出现这么多的容器那,因为每一个容器对数 ...

  9. Bluetooth篇 开发实例之十 官网的Bluetooth Chat sample app.

    运行的时候,会报错: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Action ...

  10. js常用函数和常用技巧

    学习和工作的过程中总结的干货,包括常用函数.常用js技巧.常用正则表达式.git笔记等.为刚接触前端的童鞋们提供一个简单的查询的途径,也以此来缅怀我的前端学习之路. PS:此文档,我会持续更新. Aj ...