使用快照隔离防止 SQL 视图被冗长的删除/插入事务阻塞

Posted

技术标签:

【中文标题】使用快照隔离防止 SQL 视图被冗长的删除/插入事务阻塞【英文标题】:Prevent SQL view from being blocked by lengthy delete/insert transaction using snapshot isolation 【发布时间】:2021-08-23 14:46:31 【问题描述】:

我试图防止我们网站上由 SQL 视图生成的“启动页面”在相当长的基础表更新期间被阻塞。

更新存储过程利用snapshot 隔离,生成的row versioning 允许来自正在更新的表的事务处理select 查询;在更新事务开始之前返回它们的值。很棒的东西。

不幸的是,如果我的 select 查询来自从基础表构造的 view,它们似乎仍然被阻止。

更新:事实证明这些查询在传统意义上没有被阻止,因为在sys.dm_tran_locks 中没有处于WAIT 状态的请求。但是在编译之前仍然停滞不前,等待同步统计信息完成。

感谢@Charlieface 让这个重要部分在大型更新事务期间使用SNAPSHOT 隔离来确保数据可用性!

【问题讨论】:

您是在数据库级别使用READ COMMITTED SNAPSHOT,还是使用SET TRANSACTION ISOLATION LEVEL SNAPSHOT?也许某处有更多限制性提示,例如SERIALIZABLE/HOLDLOCK/REPEATABLE READ 我现在只使用STILS。我最初在我们的测试数据库上启用了RCSI,但禁用了它——我不想继续使用它,因为它会影响所有事务的默认隔离。同样,我没有在任何查询或视图定义中使用HINTS,因为大多数文档建议避免使用它们,除非绝对必要。但如果能解决这个问题,我会考虑在这种情况下使用提示。 如果您在视图上使用READ COMMITTED 提示(在外部查询中)会发生什么? SELECT 查询被更新阻止。 在另一个查询窗口中,您能否在阻塞发生时运行以下命令select resource_type, request_mode from sys.dm_exec_tran_locks where request_status = 'WAIT' 并告诉我们结果 【参考方案1】:

在处理完 cmets 中的各种选项后,AUTO_UPDATE_STATISTICS_ASYNC 似乎被设置为 OFF

这意味着足够大的更新会导致同步统计信息刷新,进而阻止其他查询甚至编译。

如果 AUTO_UPDATE_STATISTICS_ASYNC 设置为 ON,则当前编译查询不会从统计信息更新中受益(一个小缺点),但是不会阻塞,因为统计信息是异步刷新的。

如果是ON,另一个缺点是您无法在单用户模式下访问数据库,尽管这种情况显然非常罕见,您可以暂时将其关闭。

See more in this great article,有更多非常罕见的情况当你想要它OFF

【讨论】:

谢谢,查理! 我一直在阅读MS documentation 上的AUTO_UPDATE_STATISTICS_ASYNC。他们默认关闭它的理由对我来说似乎完全违反直觉。我看不到太多的缺点,即使我发现了一些缺点,我也可以简单地将导入表移动到他们自己的数据库中并在那里打开它!再次感谢查理。

以上是关于使用快照隔离防止 SQL 视图被冗长的删除/插入事务阻塞的主要内容,如果未能解决你的问题,请参考以下文章

由于选定行的更新冲突,快照隔离事务中止

在SQL Server视图中使用快照隔离级别

mysql 不同事务隔离级别

快照隔离级别是不是可以防止幻读?

快照隔离事务由于更新冲突而中止,但没有事务开始

数据库部分