尝试完全理解SQL Server隔离级别 - 特别是可重复阅读。
我有一个启动事务的sproc并在某些数据周围放置一个光标(boo hiss)。这可能是一大块数据,因此可能需要一段时间才能完成。
然后它将COMMIT或ROLLBACK。
在此期间,在事务关闭之前,如果有人调用导致某些受影响的行的方法为READ,我的理解是此方法将停止,直到第一个方法完成。然后,他们将被提供数据(只要没有先发生超时)
我认为我是对的,但问题是 - 我是吗?!
答案 0 :(得分:20)
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.
<强>更新强>
至于你的问题:在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
答案 1 :(得分:2)
正确。
MSDN的完整说明:
指定无法读取语句 已修改但未修改的数据 尚未承担其他交易 并且没有其他交易可以 修改已被读取的数据 当前交易直到当前 交易完成。
共享锁定放在所有数据上 阅读中的每个陈述 交易并一直持续到 交易完成。这可以防止 修改任何其他交易 已经读过的行 当前交易。其他 事务可以插入新的行 符合搜索条件 当前发表的声明 交易。如果是当前的 然后事务重试该语句 它会检索新的行 导致幻像读取。因为 共享锁保持到一个结束 交易而不是被释放 在每个声明的最后, 并发性低于默认值 READ COMMITTED隔离级别。使用 此选项仅在必要时使用。