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. jQuery遍历文档(重要)

    什么是遍历? jQuery 遍历,意为"移动",用于根据其相对于其他元素的关系来"查找"(或选取)HTML 元素.以某项选择开始,并沿着这个选择移动,直到抵达您 ...

  2. UVA 10803 Thunder Mountain

    纠结在这句话了If it is impossible to get from some town to some other town, print "Send Kurdy" in ...

  3. 华为上机测试题(数字字符串转二进制-java)

    PS:此题满分,可参考 /*  * 题目:数字字符串转二进制 * 描述: 输入一串整数,将每个整数转换为二进制数,如果倒数第三个Bit是“0”,则输出“0”,如果是“1”,则输出“1”. 题目类别: ...

  4. 多个类的DLL封装及调用

    #define FaceLIBDLL #include "stdafx.h" #include "facedll.h" #include <opencv2 ...

  5. Git-stash操作

    git stash git pull git stash pop git stash pop: 从Git栈中读取最近一次保存的内容,恢复工作区的相关内容.由于可能存在多个Stash的内容,所以用栈来管 ...

  6. 【原创】Win Server 2012R2 IIS 详细配置(多图详解)

    1. 前期准备 1) 2012系统的IIS安装的时候,需要系统安装盘里面的一些软件,因此需要在安装前将系统安装盘挂载到服务器的盘符上,以便使用. 2. 添加角色和功能 打开服务器管理器,点击管理菜单, ...

  7. J.U.C并发框架源码阅读(十二)ConcurrentHashMap

    基于版本jdk1.7.0_80 java.util.concurrent.ConcurrentHashMap 代码如下 /* * ORACLE PROPRIETARY/CONFIDENTIAL. Us ...

  8. FZU-2267 The Bigger the Better(字符串,模拟)

     Problem 2267 The Bigger the Better Accept: 132    Submit: 935Time Limit: 1500 mSec    Memory Limit ...

  9. JavaScript 函数调用的 this词法

    函数调用时的this实际上是在函数被调用时发生绑定,它指向什么完全取决于函数在哪里被调用. 特例:当函数作为构造函数被调用时,即使用new 来构造一个新对象,会自动执行以下操作: [1]创建一个新对象 ...

  10. POJ 1795 DNA Laboratory(状压DP)

    [题目链接] http://poj.org/problem?id=1795 [题目大意] 给出n个字符串,求一个最小长度的串,该串包含给出的所有字符串. 要求长度最小且字典序最小. [题解] dp[i ...