我有两个问题:
1. 在这种情况下,为什么我会遇到更新冲突而不是仅仅阻止:
-- prepare
drop database if exists [TestSI];
go
create database [TestSI];
go
alter database [TestSI] set READ_COMMITTED_SNAPSHOT ON;
alter database [TestSI] set ALLOW_SNAPSHOT_ISOLATION ON;
go
use [TestSI];
go
drop table if exists dbo.call_test;
create table dbo.call_test ( Id bigint CONSTRAINT [PK_Call] PRIMARY KEY CLUSTERED ( [Id] ASC ), additional int, incl int );
create index ix_Call on dbo.call_test ( additional ) include( incl );
insert into dbo.call_test select 1, 2, 3;
go
第一個會議:
use [TestSI];
go
set transaction isolation level snapshot
begin tran
UPDATE dbo.call_test SET additional = 22 WHERE [Id] = 1
还有第二个会议:
use [TestSI];
go
set transaction isolation level snapshot
UPDATE dbo.call_test SET additional = 222 WHERE [Id] = 1
在第二个会话中,我立即遇到了以下问题:
错误消息 3960,级别 16,状态 3,行 3 由于更新冲突,快照隔离事务已中止。您不能使用快照隔离来直接或间接访问数据库“TestSI”中的表“dbo.call_test”以更新、删除或插入已被另一个事务修改或删除的行。请重试该事务或更改更新/删除语句的隔离级别。
如果我更新包含列 incl 而不是非聚集索引键,我也会遇到这种情况。
在这种情况下,非聚集索引对更新冲突有什么影响?为什么在这种情况下不使用锁定机制?
2. 第二个理论问题:
SQL Server 如何处理包含列的更新?
当我们更新此值时,SQL Server 如何更新所有具有包含列的非聚集索引?我在查询计划中没有看到任何相关信息。
select @@version
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49
版权所有 (c) Microsoft Corporation
开发者版 (64位) 在 Windows 10 Pro 10.0 上 (版本 18363: ) (Hypervisor)
我在 SQL Server 2019 上检查了这个示例,行为和我预期的一样:第二个会话被锁定。这是一个错误还是我做错了什么?