无法删除聚集主键:执行无响应且无前置错误,该排查什么?
这种情况我之前踩过类似的坑,明明已经确认没有外键引用,执行alter table Title.Parcel drop constraint PK_Parcel却一直卡着,取消后还弹出没头没尾的“See previous errors”提示。除了外键,这些点你可以逐一排查:
检查锁与阻塞情况
语句一直处于执行状态,大概率是被其他会话持有的锁阻塞了。你可以用这些语句排查:-- 查看针对该表的锁信息 SELECT * FROM sys.dm_tran_locks WHERE resource_associated_entity_id = OBJECT_ID('Title.Parcel') -- 查看阻塞链 SELECT blocking_session_id, session_id, wait_type, resource_description FROM sys.dm_os_waiting_tasks WHERE blocking_session_id IS NOT NULL如果发现有阻塞会话,要么等它释放锁,要么联系对应的会话持有者结束任务。
排查非聚集索引的依赖
聚集主键本质是聚集索引,表上的非聚集索引默认会用聚集索引键作为行定位器。如果有非聚集索引依赖聚集主键的键,删除主键时SQL Server需要自动重建这些非聚集索引——如果索引数据量很大或者有锁,就会导致卡住。你可以用下面的语句找出这类非聚集索引:SELECT i.name AS 依赖的非聚集索引名 FROM sys.indexes i JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id WHERE i.object_id = OBJECT_ID('Title.Parcel') AND i.index_id != 1 -- 排除聚集索引本身 AND ic.referenced_column_id IN ( SELECT column_id FROM sys.index_columns WHERE object_id = OBJECT_ID('Title.Parcel') AND index_id = 1 )要是找到这类索引,可以先手动删除它们,删完主键后再重新创建,能避免自动重建时的阻塞。
检查未提交的事务
有没有其他会话在这个表上开启了事务但没提交?未提交的事务会一直持有锁,阻塞你的删除操作。用下面的语句排查相关的未提交事务:SELECT st.session_id, tat.transaction_id, tat.name, tat.transaction_begin_time FROM sys.dm_tran_active_transactions tat JOIN sys.dm_tran_session_transactions st ON tat.transaction_id = st.transaction_id WHERE EXISTS ( SELECT 1 FROM sys.dm_tran_locks tl WHERE tl.transaction_id = tat.transaction_id AND tl.resource_associated_entity_id = OBJECT_ID('Title.Parcel') )检查表上的触发器
表上的触发器可能在删除主键时触发了额外操作(比如同步数据到其他表、日志记录等),导致语句卡住。你可以先查看表上的触发器:sp_helptrigger 'Title.Parcel'如果有触发器,可以先禁用它们试试:
DISABLE TRIGGER ALL ON Title.Parcel执行删除主键的语句成功后,再重新启用触发器:
ENABLE TRIGGER ALL ON Title.Parcel查看SQL Server错误日志
虽然提示“See previous errors”但你没看到具体内容,SQL Server的错误日志里可能藏着更详细的报错信息。在SSMS里找到“管理”→“SQL Server日志”,查看最近的日志条目,找找和这个表、主键删除相关的错误记录。检查数据库高可用状态(如果有)
如果你的数据库在镜像、Always On可用性组里,同步模式下可能因为节点间同步延迟导致语句卡住。可以查看镜像的同步状态,或者AG的副本同步进度,确认是不是同步问题拖慢了操作。
内容的提问来源于stack exchange,提问作者OutstandingBill

