试图完全理解 SQL Server 隔离级别 - 特别是可重复读取。
我有一个存储过程,它启动一个事务并将光标放在一些数据周围(嘘声)。这可能是相当大的数据块,因此可能需要一段时间才能完成。
然后它将提交或回滚。
在此期间,在事务关闭之前,如果有人调用了导致某些受影响的行被读取的方法,我的理解是该方法将停止,直到第一个方法完成。然后将向他们提供数据(只要没有首先发生超时)
我想我是对的,但问题是——我是吗?!
试图完全理解 SQL Server 隔离级别 - 特别是可重复读取。
我有一个存储过程,它启动一个事务并将光标放在一些数据周围(嘘声)。这可能是相当大的数据块,因此可能需要一段时间才能完成。
然后它将提交或回滚。
在此期间,在事务关闭之前,如果有人调用了导致某些受影响的行被读取的方法,我的理解是该方法将停止,直到第一个方法完成。然后将向他们提供数据(只要没有首先发生超时)
我想我是对的,但问题是——我是吗?!
REPEATABLE READ
防止SELECTs
解除他们放置的共享锁,直到事务结束。
使用事务1
作为READ COMMITTED
,您可以2
在事务中选择它后更新事务中的行1
。
使用事务1
作为REPEATABLE READ
,您在事务中选择后无法更新事务中的行。2
1
场景:
1 SELECT -- places a shared lock and immediately lifts it.
2 UPDATE -- places an exclusive lock. Succeeds.
1 SELECT -- tries to place a shared lock but it conflicts with the exclusive lock placed by 2. Locks.
1 SELECT -- places a shared lock and keeps it
2 UPDATE -- tries to places an exclusive lock but it's not compatible with the shared lock. Locks
1 SELECT -- the lock is already placed. Succeeds.
更新:
至于你的问题: in SQL Server
,SELECTs
即使使用 , 也不会相互锁定REPEATABLE READ
,因为它们放置的共享锁是相互兼容的:
CREATE TABLE t_lock (id INT NOT NULL PRIMARY KEY, value INT NOT NULL)
INSERT
INTO t_lock
VALUES (1, 1)
-- Session 1
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRANSACTION
DECLARE @id INT
DECLARE cr_lock CURSOR DYNAMIC
FOR
SELECT id
FROM t_lock
OPEN cr_lock
FETCH cr_lock
id
--
1
-- Session 2
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRANSACTION
DECLARE @id INT
DECLARE cr_lock CURSOR DYNAMIC
FOR
SELECT id
FROM t_lock
OPEN cr_lock
FETCH cr_lock
id
--
1
-- Session 1
DEALLOCATE cr_lock
COMMIT
-- Session 2
DEALLOCATE cr_lock
COMMIT
正确的。
来自MSDN的完整描述:
指定语句不能读取已被其他事务修改但尚未提交的数据,并且在当前事务完成之前没有其他事务可以修改当前事务已读取的数据。
共享锁被放置在事务中每个语句读取的所有数据上,并一直保持到事务完成。这可以防止其他事务修改当前事务已读取的任何行。其他事务可以插入与当前事务发出的语句的搜索条件匹配的新行。如果当前事务然后重试该语句,它将检索新行,从而导致幻读。因为共享锁被持有到事务结束而不是在每个语句结束时被释放,所以并发性低于默认的 READ COMMITTED 隔离级别。仅在必要时使用此选项。