Cyn*_*ker 2 sql-server delete locking sql-server-2016
目标:
删除三个表中数十亿条旧记录(大约 600GB),停机时间为零。
方法论和背景:
我计划一次删除与 100 万个 MyID 关联的批量记录(即 MyID 介于 1 和 1000000 之间)。当删除运行时,其中两个表将非常热,但第三个表上的活动可以安全地暂停。在两个热表中,MyID是聚簇键。在第三个冷表中,我在 MyID 上有一个非聚集索引。
除了 DELETE 操作之外,热表中的其他活动将包括 INSERT,可能每秒几次。MyID 是一个 IDENTITY,新插入的记录不会在任何 DELETE 批次的范围内。
如果有助于了解潜在性能,则在由 MyID 聚集的表上对这些行的样本批次进行聚合的 SELECT 花费的时间不到 1 秒,而在非聚集的表上则花费大约 2 秒。我没有这个特定数据库的产品副本可供使用,所以我不能说删除需要多长时间,但是一旦我将其部署到 DEV,我就会有一个更好的想法。
旁注:为了解决日志大小问题,我将这些批次包装在事务中,并将 TLog 备份频率从 15 分钟提高到 5 分钟。我有 150GB 的可用日志空间。
问题
我在 MS 文档中读到:
默认情况下,DELETE 语句始终在其修改的表上获取排它 (X) 锁,并保持该锁直到事务完成。
我对使用锁定提示非常谨慎,但在这种情况下我可以安全地使用锁定提示来避免 TABLOCKX 吗?除了锁定提示之外还有其他方法可以避免 TABLOCKX 吗?
删除数十亿条旧记录(约600GB)
在这种情况下,复制应保留的行可能比删除更方便。请注意,所有 600Gb 肯定都会移动到您的日志文件中。
默认情况下,DELETE 语句始终在其修改的表上获取排它 (X) 锁,并保持该锁直到事务完成。
这是错误的。table lock除非指定了相应的提示,否则SQL Server 永远不会启动。
默认情况下,SQL Server 将获取尽可能细粒度的锁,以获得最大的并发性。在大多数情况下,这意味着 SQL Server 将获取行(RID 或 KEY)锁。SQL Server 可以在单个表中的数据上获取数百或数千个单独的锁,而不会造成任何问题。然而,在某些情况下,如果 SQL Server 确定查询将访问聚集索引中的一系列行,则它可能会获取页锁。毕竟,如果要访问页面上的每一行,则管理单个页面锁比管理数十或数百个行锁更容易。在其他情况下,主要是当没有可用索引来帮助处理查询时,SQL Server 可能会在处理查询开始时锁定整个表。
在您对范围进行过滤的情况下PK:MyID BETWEEN 1 AND 1000000它很可能会从锁开始page。这一切都取决于一个记录可以容纳多少条记录page。如果以粒度锁定1000000记录所page花费的时间少于5000锁,那么您就可以使用锁,如果每个语句page有更多的锁,那么您的表将被完全锁定。lockslock escalation
...
除了在超过实例范围阈值时升级锁之外,当任何单个会话在单个语句中获取超过 5,000 个锁时,SQL Server 也会升级锁。在这种情况下,选择哪个会话将其锁升级并不具有随机性;这是获取锁的会话。
SQL Server 并发性:锁定、阻塞和行版本控制作者:K.Delaney
因此,只有通过测试和监控所获取的锁,您才能找到最佳方案batch size并避免lock escalation。batch size如果您知道表中每页的平均行数,则可以大致计算出您的值。PAGLOCK或者,您可以通过使用甚至禁用表上的锁升级来强制页面锁定:
ALTER TABLE MyTable SET ( LOCK_ESCALATION = DISABLE )
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5678 次 |
| 最近记录: |