SQL 服务器读取已提交的快照
SQL Server Read Committed Snapshot
我只是想知道有关已提交读隔离级别的快照行为的一些信息。假设我有一个名为 "A" 的 table。这是第一笔交易:
Select blabla
From A
Insert Into A blabla
第二笔交易做同样的事情
Select blabla
From A
Insert Into A blabla
并假设以下时间线发生:
Tran1: select
Tran1: insert (not yet committed)
Tran2: select (I don't know it is possible or not)
Tran2: insert
据我所知,在标准的读取已提交隔离级别中,tran2 select 查询将被阻止,因为 tran1 插入命令尚未提交或回滚。但是,虽然启用了 "is_read_committed_snapshot",但我预计在插入或更新命令期间不会获取任何锁。
那么 tran2 会怎样?
我希望 tran2 select 查询不会看到 tran1 插入的数据,因为它会是 "dirty read"。但它也不会被阻止。
因为tran1插入查询没有获取任何锁,这种情况不会是这两个事务执行的并发问题吗?
假设您是这样做的:
SELECT id FROM customers
BEGIN TRAN new_tran
UPDATE customers
设置 ID = '1'
其中 ID = '01'
如果您的查询是这样的:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
BEGIN TRAN
SELECT *
FROM customers
WHERE id = '01'
结果 - 即使我们将值更改为 01,我们仍然会在会话 2 (2, TWO) 中看到旧记录。
现在,让我们在会话 1 中提交事务
现在假设您在会话 2 中提交事务,现在您将获得新的更新值:
COMMIT
SELECT *
FROM DemoTable
WHERE i = 2
您可以在 Pinal Dave 的博客上阅读更多相关信息:blog.sqlauthority.com/2015/07/03/sql-server-difference-between-read-committed-snapshot-and-snapshot-isolation-level/
I expect that any of lock won't acquired during insert or update
command.
这是错误的。即使您已启用 RCSI
,写入器仍会阻止写入器,并且仍会获得 X
锁。
RC 和 RCSI 之间的区别在于阅读行为。
在悲观 RC 上工作时,来自 Tran2 的 SELECT
将被 A 上持有的 X
锁阻塞,而在 RCSI Tran2 上工作时 SELECT
将不会被阻塞,它将与最后提交的一起提供A 的版本,即 A 的状态 before Tran1 修改了它。
接下来会发生什么取决于您的 table 组织和您 INSERT
。
一些例子。
1) table A 是一个堆,你在两个事务中都做单插入。
在这种情况下,您在 Tran2 中的 INSERT
在任何情况下都会成功,无论您是否尝试在两个事务中插入相同的值,因为在这种情况下,服务器获取的是 table 上的 IX
(与 Tran1 持有的 IX
兼容),页面上的 IX
(也与 IX
由 Tran1 持有,即使它是同一页),并且 X
在 RID 上(而 Tran1 在 另一个 RID 上有 X
),所以有没有冲突。
2) table A 被聚类 table,您正试图在此 table 中插入 相同的新密钥 。
在这种情况下,您的 Tran2 的 INSERT
将被阻止,因为同一键上的两个 X
锁之间存在冲突,第一个由 Tran1 持有,第二个由 Tran2 请求并且是已屏蔽。
3) table A 被聚类 table,您正试图在此 table.[=31= 中插入 不同的键 ]
Insert2 将成功,因为 Tran2 请求的密钥 X
锁定将被授予,因为 Tran1 在 table、IX
和 [=11 上持有 IX
=] 在 another
键上。
我只是想知道有关已提交读隔离级别的快照行为的一些信息。假设我有一个名为 "A" 的 table。这是第一笔交易:
Select blabla
From A
Insert Into A blabla
第二笔交易做同样的事情
Select blabla
From A
Insert Into A blabla
并假设以下时间线发生:
Tran1: select
Tran1: insert (not yet committed)
Tran2: select (I don't know it is possible or not)
Tran2: insert
据我所知,在标准的读取已提交隔离级别中,tran2 select 查询将被阻止,因为 tran1 插入命令尚未提交或回滚。但是,虽然启用了 "is_read_committed_snapshot",但我预计在插入或更新命令期间不会获取任何锁。
那么 tran2 会怎样?
我希望 tran2 select 查询不会看到 tran1 插入的数据,因为它会是 "dirty read"。但它也不会被阻止。
因为tran1插入查询没有获取任何锁,这种情况不会是这两个事务执行的并发问题吗?
假设您是这样做的:
SELECT id FROM customers
BEGIN TRAN new_tran
UPDATE customers
设置 ID = '1' 其中 ID = '01'
如果您的查询是这样的:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
BEGIN TRAN
SELECT *
FROM customers
WHERE id = '01'
结果 - 即使我们将值更改为 01,我们仍然会在会话 2 (2, TWO) 中看到旧记录。
现在,让我们在会话 1 中提交事务
现在假设您在会话 2 中提交事务,现在您将获得新的更新值:
COMMIT
SELECT *
FROM DemoTable
WHERE i = 2
您可以在 Pinal Dave 的博客上阅读更多相关信息:blog.sqlauthority.com/2015/07/03/sql-server-difference-between-read-committed-snapshot-and-snapshot-isolation-level/
I expect that any of lock won't acquired during insert or update command.
这是错误的。即使您已启用 RCSI
,写入器仍会阻止写入器,并且仍会获得 X
锁。
RC 和 RCSI 之间的区别在于阅读行为。
在悲观 RC 上工作时,来自 Tran2 的 SELECT
将被 A 上持有的 X
锁阻塞,而在 RCSI Tran2 上工作时 SELECT
将不会被阻塞,它将与最后提交的一起提供A 的版本,即 A 的状态 before Tran1 修改了它。
接下来会发生什么取决于您的 table 组织和您 INSERT
。
一些例子。
1) table A 是一个堆,你在两个事务中都做单插入。
在这种情况下,您在 Tran2 中的 INSERT
在任何情况下都会成功,无论您是否尝试在两个事务中插入相同的值,因为在这种情况下,服务器获取的是 table 上的 IX
(与 Tran1 持有的 IX
兼容),页面上的 IX
(也与 IX
由 Tran1 持有,即使它是同一页),并且 X
在 RID 上(而 Tran1 在 另一个 RID 上有 X
),所以有没有冲突。
2) table A 被聚类 table,您正试图在此 table 中插入 相同的新密钥 。
在这种情况下,您的 Tran2 的 INSERT
将被阻止,因为同一键上的两个 X
锁之间存在冲突,第一个由 Tran1 持有,第二个由 Tran2 请求并且是已屏蔽。
3) table A 被聚类 table,您正试图在此 table.[=31= 中插入 不同的键 ]
Insert2 将成功,因为 Tran2 请求的密钥 X
锁定将被授予,因为 Tran1 在 table、IX
和 [=11 上持有 IX
=] 在 another
键上。