SQL Server读取提交的快照

时间:2017-10-30 22:00:54

标签: sql-server concurrency transactions isolation-level

我只是想知道有关读提交隔离级别的快照行为。我们假设我有一个名为“A”的表。这是第一笔交易:

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 insert命令尚未提交或回滚。但是,虽然启用了“is_read_committed_snapshot”,但我希望在插入或更新命令期间不会获取任何锁定。

那么tran2会发生什么?

我希望tran2 select查询不会看到tran1插入的数据,因为它将是“脏读”。但它也不会受阻。

由于tran1 insert查询没有获取任何锁定,这种情况不会成为执行这两个事务的并发性问题吗?

2 个答案:

答案 0 :(得分:3)

  

我希望在插入或更新期间不会获取任何锁定   命令。

那是错的。即使您已启用RCSI,编写者仍会阻止编写者,并且X锁仍然可以获取。

RC和RCSI之间的区别在于读取行为。 在处理悲观RC时,来自Tran2的SELECT将在A上保持的X锁上被阻止,而在RCSI Tran2的SELECT上工作将不会被阻止,它将被提供最后一次提交A的版本,即状态为之前 Tran1已修改它。

然后发生什么取决于您的表格组织以及您INSERT的内容。

一些例子。

1)表A是一个堆,您在两个事务中都进行单个插入。

在这种情况下,Tran2中的INSERT在任何情况下都会成功,它与您尝试在两个事务中插入的值相同或不是,因为服务器在此获取了什么大小写为IX在桌面上(与Tran1持有的IX兼容),IX在页面上(也与Tran1持有的IX兼容,即使它是同一页面)和RID上的X(而Tran1在另一个 RID上有X,所以没有冲突。

2)表A是群集表,您试图在此表中插入相同的新密钥

在这种情况下,你的Tran2的INSERT将被阻止,因为同一个键上的两个X锁定之间存在冲突,第一个由Tran1保持,sent由Tran2请求并被阻止。

3)表A是群集表,您试图在此表中插入不同的密钥

插入2将成功,因为Tran2请求的X锁定将被授予,因为Tran1持有IX在桌面上,IX在页面上,X在{{1}上密钥。

答案 1 :(得分:0)

让我们说你这样做:

SELECT id FROM customers

BEGIN TRAN new_tran
UPDATE customers

SET 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/