使用RCSI可以使普通的数据库读取操作不再善用Share Lock,但不是所有的读操作都不会被阻塞。
我一开始就把这个“读取操作”无限放大,认为从此不再有读/写操作相互阻塞的事情了。下面是不久之前系统里的一个例子,用来说明更新操作中,当SQL SERVER引擎用来确认更新范围的时候并不会读取快照,而是会使用和X锁不兼容的U锁。因此,即使一个语句的最终结果不会更新任何记录,他还是有可能会被阻塞。
/*
SegmentA
*/
BEGIN TRAN
UPDATE CL_CCMX
SET [ JSDID ] = 1
WHERE /* Confition1 */
ROLLBACK
BEGIN TRAN
UPDATE CL_CCMX
SET [ JSDID ] = 1
WHERE /* Confition1 */
ROLLBACK
开两个会话分别执行SegmentA和SegmentB,会发现,SegmentB被阻塞。查看会话和锁情况:
解决办法比较笨,将Where条件更换为使用临时表:
/*
Solution
*/
BEGIN TRAN
SELECT CCMXID
INTO #IDs
WHERE /* Confition */
UPDATE CL_CCMX
SET [ JSDID ] = 1
WHERE CCMXID IN ( SELECT ID FROM #IDs)
ROLLBACK
BEGIN TRAN
SELECT CCMXID
INTO #IDs
WHERE /* Confition */
UPDATE CL_CCMX
SET [ JSDID ] = 1
WHERE CCMXID IN ( SELECT ID FROM #IDs)
ROLLBACK
事情过去一段时间了。小记一把。