首页 > 代码库 > DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用

DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用

本文主要解释下DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用

实验环境:

DB2 v9.7.0.6
AIX 6.1.0.0
采用默认的隔离级别CS

STUDENT表的DDL与初始内容
CREATE TABLE "E97Q6C  "."STUDENT"  (
                  "AGE" INTEGER , 
                  "NAME" CHAR(8) )   

                 IN "USERSPACE1" ; 


$ db2 "select * from student"
AGE         NAME    
----------- --------
          3 xu      
          5 gao     
          6 mu      
          6 mu      
          6 mu      
          4 three   
          1 an      
  7 record(s) selected.

--分割线--

当启用DB2_EVALUNCOMMITTED时,DB2可以对未提交的插入(INSERT)或更新(UPDATE)数据进行谓词判断。
如果未提交的数据不符合该条语句的谓词判断条件,DB2将不对未提交数据加锁,这样避免了因为要对
未提交数据加锁引起的锁等待状态,提高了应用程序访问的并发性。


实验 1
测试如下(该参数与数据库配置参数CUR_COMMIT有冲突,因此,测试之前需要先将CUR_COMMIT参数设为disabled.)
首先在session 1里做一条“未提交的插入(INSERT)操作”

session 1
---------
$ db2 +c "insert into student values(7,‘he‘)"
DB20000I  The SQL command completed successfully.

session 2
---------
$ db2 "select * from student"
SQL0911N  The current transaction has been rolled back because of a deadlock 
or timeout.  Reason code "68".  SQLSTATE=40001
$ db2 "select * from student where age = 3"
SQL0911N  The current transaction has been rolled back because of a deadlock 
or timeout.  Reason code "68".  SQLSTATE=40001

可以看到,在session 2里的两条语句都因锁超时而失败了。原因是如果用户在更改(UPDATE)、插入(INSERT)或
删除(DELETE)一行时,会在这一行加上排它锁,别的用户不能读、写,除非使用UR隔离级别。

现在启用DB2_EVALUNCOMMITTED变量,需要重启实例,之后在session 1里做同样的插入操作,session 2里做同样的查询
操作:

session 1

------------
$ db2set DB2_EVALUNCOMMITTED=ON
$ db2stop force
$ db2start

$ db2 connect to qsmiao
$ db2 +c "insert into student values(7,‘he‘)"
DB20000I  The SQL command completed successfully.


session 2
------------
$ db2 "select * from student"
SQL0911N  The current transaction has been rolled back because of a deadlock 
or timeout.  Reason code "68".  SQLSTATE=40001
$ db2 "select * from student where age = 3"
AGE         NAME    
----------- --------
          3 xu      
  1 record(s) selected.

这次可以看到第2条查询语句是成功的,原因是session 1中有未提交的插入操作,session 2在扫描时,对该行进行了谓词判断,发现不符合谓词盼断条件
也就是 age = 3 , session 2就不会对该行进行加锁,因而不会导致锁超时。

DB2_SKIPDELETED
变量被启用的效果是:在表访问期间,会无条件地跳过被删除的行。

实验 2:
在默认情况下,即没有设置DB2_EVALUNCOMMITTED和DB2_SKIPDELETED变量的时候,如果session 1用提交的方式删除操作的时候,Session 2若要查询整个表,是要超时的,
如下:
session 1
---------
$ db2set DB2_SKIPDELETED=OFF
$ db2set DB2_EVALUNCOMMITTED=OFF
$ db2stop force
$ db2start
$ db2 connect to qsmiao
$ db2 +c "delete from student where age=6"
DB20000I  The SQL command completed successfully.


session 2
---------
$ db2 "select * from student"
SQL0911N  The current transaction has been rolled back because of a deadlock 
or timeout.  Reason code "68".  SQLSTATE=40001 


如下,现在修改DB2_SKIPDELETED为ON,那么session 2查询的时候,会无条件地跳过被删除的行,因此会成功。
session 1
---------
$ db2 rollback
$ db2set DB2_SKIPDELETED=ON
$ db2stop force
$ db2start
$ db2 connect to qsmiao
$ db2 +c "delete from student where age=6"
DB20000I  The SQL command completed successfully.


session 2
---------
$ db2 "select * from student"


AGE         NAME    
----------- --------
          3 xu      
          5 gao     
          4 three   
          1 an      


  4 record(s) selected.


类似的,
DB2_SKIPINSERTED变量的作用是无条件地跳过被插入的行,就像它们还没有被插入。


参考资料:
牛新庄 《高级进阶DB2(第2版)》


DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用