相关疑难解决方法(0)

为什么我收到“由于更新冲突而中止快照隔离事务”?

我们有两张桌子

  1. 父级(Id int 身份、日期日期时间、名称 nvarchar)
  2. 孩子(Id int 身份、ParentId int、日期日期时间、名称 nvarchar)

Child 与 Parent 有外键关系。

我们启用了数据库级读提交快照隔离。

我们只为父和子插入和删除行(无更新)

我们有一个进程(事务)从 Child(然后是 Parent)中删除旧数据

我们有多个其他进程(事务)将新数据插入父(然后是子)

删除过程会定期(但不是所有时间)回滚,即使插入过程没有插入新的子行,这些子行引用删除要删除的父行 - 它只是创建新的父行和一个或多个引用新父级的新子行

删除父行时的错误是:

由于更新冲突,快照隔离事务中止。您不能使用快照隔离直接或间接访问数据库 'Test' 中的表 'dbo.Child' 以更新、删除或插入已被另一个事务修改或删除的行。重试事务或更改更新/删除语句的隔离级别。

我知道人们建议在外键列上建立索引 - 我们不希望在理想情况下(出于空间/性能原因)这样做 - 除非这是使其工作的唯一可靠方法。

注意到这一点:https : //stackoverflow.com/questions/10718668/snapshot-isolation-transaction-aborted-due-to-update-conflict

和相当不错的文章:https : //sqlperformance.com/2014/06/sql-performance/the-snapshot-isolation-level

但这些都没有给我想要的理解:)

sql-server snapshot-isolation

9
推荐指数
1
解决办法
1万
查看次数

如何避免表锁升级?

我有一项任务要更新生产表中的 500 万行,而无需长时间锁定整个表

所以,我使用了多次帮助我的方法 - 一次更新前 (N) 行,块之间的间隔为 1-N 秒

这次从一次更新前 (1000) 行开始,监视扩展事件会话中的lock_escalation事件

lock_escalation在每次更新操作期间出现,所以我开始将每个块1000 -> 500 -> 200 -> 100 -> 50行的行数降低到 1

之前(不是使用这个表,并且对于删除操作 - 不是更新),将行数降低到 200 或 100,有助于摆脱lock_escalation事件
但是这一次,即使每 1 次更新操作有 1 行,表lock_escalation仍然显示。每次更新操作的持续时间大致相同,无论是一次 1 行还是 1000 行

在我的情况下如何摆脱表锁升级?

@@TRANCOUNT 为零

扩展事件:

扩展事件

代码

set nocount on

declare 
    @ChunkSize              int = 1000,                         -- count rows to remove in 1 chunk 
    @TimeBetweenChunks      char(8) = '00:00:01',               -- interval between chunks
    
    @Start                  datetime,
    @End …
Run Code Online (Sandbox Code Playgroud)

sql-server extended-events lock-escalation sql-server-2017 batch-processing

6
推荐指数
1
解决办法
602
查看次数