|
第一个是在DB2 FOR LUW上面的:
现在有一个表deadtable, 只有一列C1(INT 4),同时在C1上定义了INDEX和KEY
现在里面有四条记录 11,22,33,44
STEP 1.在线程A执行 +C UPDATE DEADTABLE SET C1=1 WHERE C1 = 11
STEP 2.在线程B执行 +C SELECT * FROM DEADTABLE WHERE C1 =22
STEP 3.在线程B执行 +C SELECT * FROM DEADTABLE WHERE C1 =33
STEP 4.在线程B执行 +C SELECT * FROM DEADTABLE WHERE C1 =22 OR C1 =33
从偶的水平和接触到的资料来看,默认的Cursor Stability的情况下,update一条记录应该用的是行锁,不会影响其他纪录的查询或写入。
在上面的测试中,step 2,3确实也能正常的完成并得到结果。
问题处在step 4里面,当where条件中使用了or的时候,虽然按理说db2还是应该用index去直接找出这两行,但是实际上这个时候线程B却等待在了C1=11的行锁上。除非STEP1 中的线程A COMMIT,要不然线程 B会一直等待着。
而用
+C SELECT * FROM DEADTABLE WHERE C1=22
UNION ALL
SELECT * FROM DEADTABLE WHERE C1=33
去替换掉STEP 4的SQL的时候,又能正常返回了(这个时候其实和STEP2 ,3应该完全等价吧)
有哪位Boss能帮我解惑一下下么,where条件中的or是如何导致这个结果的阿?
第二个问题是处在db2 for mainframe上的:
分别在两个job里面提交下面的sql(当然先submit递归select的那个,然后再提交update)
SQL 1:
WITH TEMPTAB(CID, PID, LEVEL) AS
( SELECT CUSTID,PROVINCEID,1
FROM GDC272.GDC272_EMPLAB1
WHERE CUSTID =123
UNION ALL
SELECT G.CUSTID,G.PROVINCEID,T.LEVEL+1
FROM TEMPTAB T, GDC272.GDC272_EMPLAB1 G
WHERE T.LEVEL<1000000
AND G.CUSTID =123
AND G.PROVINCEID = T.PROVINCEID
)
SELECT COUNT(*) FROM TEMPTAB
+
SQL 2:
UPDATE GDC272.GDC272_EMPLAB1
SET PROVINCEID =333
WHERE CUSTID = 123 ;
按理说默认游标级别的查询不加锁,UPDATE可以执行,但是这里却一直是因为等待时间过长而导致sqlcode=-911了。
然后再在db2 for LUW上,尝试在两个不同的线程里面提交和上面等价功能的sql:
SQL 1:
WITH TEMPTAB(C1, LEVEL) AS
( SELECT C1,1
FROM DEADTABLE
WHERE C1 = 44
UNION ALL
SELECT D.C1, T.LEVEL+1
FROM TEMPTAB T, DEADTABLE D
WHERE T.LEVEL<10000000
AND D.C1 = 44
)
SELECT COUNT(*) FROM TEMPTAB
+
SQL 2:
UPDATE DEADTABLE SET C1 = 4 WHERE C1 = 44;
发现sql 2提交后,马上就完成了数据的修改,正在执行中的sql 1因为 C1=44的纪录已经被修改为4,所以递归SELECT中断,TEMPTAB中的纪录不到10000000 条
也就是说,这个代码在LUW上面能并发执行,但是在MAINFRAME上会导致死锁。
看了好多天,还是百思不得其解,盼高手解惑ING. |
|