IT *_*her 5 sql-server transaction locking snapshot-isolation
如果在具有“读取已提交快照”隔离级别的表上运行更新并且提交未决
例如:
update table1 set col1 = col1 + 1 where PKcol < 3update table1 set col1 = col1 + 1 where PKcol = 3update table1 set col1 = col1 + 1 where NonPKcol < 3update table1 set col1 = col1 + 1 where NonPKcol = 3update table1 set col1 = col1 + 1 where PKcol < 3 and NonPKcol = 5在上述情况下,PKcol 是表中的主键,而 NonPKcol 是非主键。
是否只为满足“where”条件的行锁定更新?它是基于值、索引还是主列?
并发修改的确切行为部分取决于 SQL Server 选择的访问路径来定位要更改的记录。
如果 SQL Server 使用聚集索引来定位要更改的数据,则通常会对聚集索引键(和/或页面等)进行锁定。如果 SQL Server 使用非聚集索引定位要更改的行,则将对非聚集索引进行锁定。在这两种情况下,在实际执行修改之前,通常也会对聚集索引进行排他锁。
预测锁定行为可能是一项有趣且具有教育意义的练习,但通常会提出错误的问题。如果您在似乎没有必要的情况下遇到锁定阻塞,那么这可能是正确的问题,但这是一个非常高级的问题,需要详细的内部知识才能完全解释。稍后我将根据您的数据展示一个示例。
大多数情况下,真正的问题是“我应该使用哪种隔离级别?”。锁是一个实现细节,用于提供各种隔离级别提供的保证。保证是最重要的。您应该了解每个隔离级别下可能出现的不同行为,然后做出明智的选择。有关所有详细信息,请参阅该链接。
修改数据时,RCSI行为与标准相同READ COMMITTED。如果它需要读取当前被另一个会话未提交的更改锁定的内容,它将被阻止。一旦阻塞会话提交或回滚其更改,阻塞更新将继续,读取阻塞锁释放时存在的提交值。此行为是防止“丢失更新”所必需的,这在 SQL Server 支持的任何隔离级别下都是不允许的。
下面的演示表明,精确的阻塞行为取决于根据优化器选择的查询计划需要哪些锁。在某些情况下,更新会阻止,在其他情况下,它不会。SQL Server 始终尊重用户隔离级别提供的保证,而不管实现定义的锁定行为。
CREATE TABLE dbo.Table1
(
PKcol integer PRIMARY KEY,
NonPKCol integer NULL UNIQUE,
col1 integer NULL
);
INSERT dbo.Table1
(PKcol, NonPKCol, col1)
VALUES
(1,1,0),
(2,2,0),
(3,3,0),
(4,4,0),
(5,5,0);
Run Code Online (Sandbox Code Playgroud)
在单独的连接上,运行:
BEGIN TRANSACTION;
UPDATE dbo.Table1 SET NonPKCol = 997 WHERE PKcol = 3;
UPDATE dbo.Table1 SET NonPKCol = 998 WHERE NonPKCol = 3;
UPDATE dbo.Table1 SET NonPKCol = 999 WHERE NonPKCol = 5;
Run Code Online (Sandbox Code Playgroud)
请注意缺少 aCOMMIT或ROLLBACK TRANSACTION。
-- (1) Succeeds (no conflicting locks encountered)
update table1 set col1 = col1 + 1 where PKcol < 3
-- (2) Waits for an X lock for clustered index key PKcol = 3
update table1 set col1 = col1 + 1 where PKcol = 3
-- (3) Waits on U lock for clustered index key PKcol = 3
update table1 set col1 = col1 + 1 where NonPKcol < 3
-- (3) Succeeds when read access is by NONCLUSTERED index
update t set col1 = col1 + 1 from table1 t with(index(2)) where NonPKcol < 3
-- (4) Blocks on U lock for NONCLUSTERED index key NonPKcol = 3
update table1 set col1 = col1 + 1 where NonPKcol = 3
-- (5) Blocks on U lock for nonclustered index key NonPKcol = 5
update table1 set col1 = col1 + 1 where PKcol < 3 and NonPKcol = 5
-- (5) Succeeds when access is by CLUSTERED index
update t set col1 = col1 + 1 from table1 t with(index(1)) where PKcol < 3 and NonPKcol = 5
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1740 次 |
| 最近记录: |