我只是想知道有关读提交隔离级别的快照行为。我们假设我有一个名为“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查询没有获取任何锁定,这种情况不会成为执行这两个事务的并发性问题吗?
答案 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/