Cat*_*tNZ 2 sql-server locking
*编辑:结果证明这里的答案中没有任何解决方案,我在Python中使用SQLAlchemy,它是一个ORM。我在事务中执行下面的删除语句,但从未提交它。这导致发生大约 10 个打开的事务,最终所有事务都需要回滚,从而锁定整个表,直到回滚完成。
给定以下表结构,将使用最近日期时间的 update_time 连续插入记录。与数据库的单独连接会定期修剪日期超过 2 周的旧记录。
表结构:
以下插入运行非常频繁,具有不同的值:
重复以下删除语句直到需要为止,然后立即运行 select 以查看该过程是否完成
delete top(5000) from trade_options with (READPAST) where update_time < '<Two Weeks Ago>'
Run Code Online (Sandbox Code Playgroud)
活动监视器显示删除正在锁定,插入正在等待(LCK_M_IX):
谢谢
**编辑:这是作为脚本输出的索引/键
CREATE NONCLUSTERED INDEX [IX_order_option] ON [dbo].[order_option]
(
[update_time] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE [dbo].[order_option] ADD PRIMARY KEY CLUSTERED
(
[exchange_id] ASC,
[symbol] ASC,
[update_time] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
您的问题的名称为lock escalation
。您可以在此处阅读更多相关内容:如何解决 SQL Server 中锁升级引起的阻塞问题。
默认情况下,SQL Server 将获取尽可能细粒度的锁,以获得最大的并发性。在大多数情况下,这意味着 SQL Server 将获取行(RID 或 KEY)锁。SQL Server 可以在单个表中的数据上获取数百或数千个单独的锁,而不会造成任何问题。然而,在某些情况下,如果 SQL Server 确定查询将访问聚集索引中的一系列行,则它可能会获取页锁。毕竟,如果要访问页面上的每一行,则管理单个页面锁比管理数十或数百个行锁更容易。在其他情况下,主要是当没有可用索引来帮助处理查询时,SQL Server 可能会在处理查询开始时锁定整个表。
indexes
在你的情况下,我怀疑表上有一些(这意味着delete
也获取了它们的锁)或者你在其中进行了删除transaction
(这意味着所有的都locks
被保留到了末尾transaction
)。在这种情况下会发生这种情况:
当任何单个会话在单个语句中获取超过 5,000 个锁时, SQL Server 将升级锁。在这种情况下,选择哪个会话将其锁升级并不具有随机性;这是获取锁的会话。
因此,您应该摆脱包装transaction
(如果存在),或减少batch size
到较小的包装,或lock escatation
在此表上禁用:
alter table order_option
set ( lock_escalation = disable )
Run Code Online (Sandbox Code Playgroud)
您认为将删除批次降低到 5000 以下,或者删除索引会有帮助吗?在删除索引的情况下,这不会大大减慢删除速度吗?
你不应该放弃这个index
,它可以帮助你delete
。
你可以批量尝试一下2000 rows
,应该会有帮助。
我不知道与此相关的查询类型table
,但使用clustered index
onupdate_time
和PK
as可能是有意义的nonclustered
归档时间: |
|
查看次数: |
7591 次 |
最近记录: |