可重复阅读 - 我理解这一点吗?

时间:2010-01-14 16:22:27

标签: sql-server isolation-level

尝试完全理解SQL Server隔离级别 - 特别是可重复阅读。

我有一个启动事务的sproc并在某些数据周围放置一个光标(boo hiss)。这可能是一大块数据,因此可能需要一段时间才能完成。

然后它将COMMIT或ROLLBACK。

在此期间,在事务关闭之前,如果有人调用导致某些受影响的行的方法为READ,我的理解是此方法将停止,直到第一个方法完成。然后,他们将被提供数据(只要没有先发生超时)

我认为我是对的,但问题是 - 我是吗?!

2 个答案:

答案 0 :(得分:20)

REPEATABLE READ阻止SELECTs解除他们放置的共享锁,直到事务结束。

将事务1设为READ COMMITTED,您在事务2中选择事务后,可以更新事务1中的行。

将事务1设为REPEATABLE READ,您在事务2中选择事务后,无法更新事务1中的行。

场景:

READ COMMITTED

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.

REPEATABLE READ

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隔离级别。使用   此选项仅在必要时使用。