Cyn*_*ker 4 sql-server locking sql-server-2016
我的研究表明,我可以在短时间内删除表中的一列(前提是我获得了排他锁),因为这只是元数据更改。
该表有两个不同的服务,不断插入和更新记录。太热了。如果不开发这种活动级别的完整复制环境,我怎么能确保像这样的陈述
ALTER TABLE x DROP COLUMN y
Run Code Online (Sandbox Code Playgroud)
会成功获得排他锁,快速做drop,然后解锁表吗?
SQL Server 将如何将此请求排队(例如,先进先出)?我能确定 DROP COLUMN 真的只需要几分钟吗?
在 PROD 中长时间锁定此表是不可接受的,因此我试图避免出现意外。
其他注意事项:稍后我将在线重新索引以对索引进行碎片整理并回收空间。
SQL Server 将如何将此请求排队(例如,先进先出)?我能确定 DROP COLUMN 真的只需要几分钟吗?
ALTER TABLE 的锁定方式是您需要一个架构修改锁 (Sch-M) 来执行 ALTER。涉及该表的每个其他查询都需要架构稳定性锁 (Sch-S)。Sch-M 和 Sch-S 不兼容。
此外,在您等待获取 Sch-M 锁时,您会阻止对 Sch-S 锁的任何新请求。因此,您等待所有进行中的查询和事务释放表上的 Sch-S 锁,并在等待时阻止所有新查询。这是 DDL 锁定的正常工作方式,只要您的表上没有任何长时间运行的查询,它就可以正常工作。
但是,如果您有长时间运行的查询,而您的 DDL 可能会卡在后面,那么您的 DDL 反过来会阻止所有新查询。因此,在繁忙的系统上运行 DDL 并同时进行短期和长期运行是一个问题。
低优先级等待通过允许您的 DDL 语句以降低的优先级等待,而不是阻止新查询来解决这个问题。DDL 会话将等待一个“窗口”,在该窗口中没有其他会话对表有任何锁定,然后运行。但由于 DDL 会话不会阻止新查询,因此它可能会永远等待。
不幸的是,没有为删除列启用低优先级等待。您可以创建一个反馈项目以要求在此处实施。已启用在线索引重建和分区切换。
大多数情况下,您可以使用 LOCK_TIMEOUT来模拟此行为并重试。因此,请使用锁定超时配置您的 DDL 会话,这样如果无法快速获取锁定,它将放弃 ALTER TABLE。
所以像这样运行alter:
set lock_timeout 1000 --1 second
alter table SomeTable
drop column if exists ColumnToDrop
Run Code Online (Sandbox Code Playgroud)
它要么很快成功,要么因锁定超时错误而失败。如果您想在无人值守的作业中运行它,您可以使用重试循环继续尝试,直到 ALTER TABLE 快速成功。
像这样的东西:
set lock_timeout 1000 --1 second
declare @tries int = 0
while 1=1
begin
begin try
set @tries = @tries + 1;
alter table SomeTable
drop column if exists ColumnToDrop
print 'complete'
break;
end try
begin catch
if @tries > 10 or error_number() <> 1222 throw;
declare @msg nvarchar(2000) = concat('retry ', @tries);
print @msg
end catch
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
968 次 |
| 最近记录: |