设为首页 加入收藏

TOP

DB2锁问题分析与解释(二)
2014-11-23 17:50:51 】 浏览:762
Tags:DB2 问题 分析 解释
tatement 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

\


结论: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

\

$ 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 = 'fou
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇db2生产应用监控 下一篇常用的DB2命令(2)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目