SQL Server删除数据时如何跳过被锁定的行?
SQL Server删除数据时如何跳过被锁定的行?
哥们儿,我太懂你这种被锁行卡得欲哭无泪的感觉了!之前维护ERP数据的时候也碰到过一模一样的问题——DELETE任务被锁定的数据堵到天荒地老,试了NOLOCK和READPAST一开始还没见效,折腾好久才搞明白门道。
先给你掰扯清楚为啥你之前的尝试没成功:
NOLOCK(也就是READ UNCOMMITTED隔离级别)其实是给读操作准备的,它能让你读到未提交的脏数据,但对DELETE这种写操作完全没用——毕竟你要修改数据,就算读的时候能看到锁着的行,真要动手删的时候还是会被排他锁给堵死。READPAST本身确实是用来跳过锁定行的,但你可能没把它用对地方!它不是随便加个提示就行,得精准应用到你要操作的目标表上。
给你几个亲测有效的方案:
1. 直接在DELETE语句里加READPAST提示
最简单的写法就是把READPAST绑定到目标表上,这样DELETE的时候会自动跳过被其他事务锁定的行:
DELETE TOP (1000) erp_table FROM YourERPTable erp_table WITH (READPAST) WHERE IsOutdated = 1; -- 这里换成你的过时数据判断条件
我特意加了TOP (1000),建议你批量删除,别一次性删所有数据——就算碰到锁,也只会卡这1000行的处理,不会整个任务直接停住。
2. 配合ROWLOCK缩小锁定粒度
如果ERP系统的锁粒度比较大(比如页锁),可以再加个ROWLOCK提示,强制SQL Server用行级锁,进一步降低被堵的概率:
DELETE TOP (1000) erp_table FROM YourERPTable erp_table WITH (READPAST, ROWLOCK) WHERE IsOutdated = 1;
3. 循环批量删除(更稳妥的长期方案)
要是过时数据量特别大,建议写个循环脚本,每次删一批,直到没有符合条件的数据为止:
WHILE 1 = 1 BEGIN DELETE TOP (1000) erp_table FROM YourERPTable erp_table WITH (READPAST, ROWLOCK) WHERE IsOutdated = 1; -- 如果这次没删到数据,就退出循环 IF @@ROWCOUNT = 0 BREAK; -- 可选:每次删完歇1秒,给ERP系统留点资源 WAITFOR DELAY '00:00:01'; END
最后提醒你一句:READPAST只能跳过行级锁锁定的数据,如果ERP系统是锁整个表或者锁页,那这个提示就没用了——不过一般ERP系统处理数据都是行级锁,这个方案应该能解决你的问题。
备注:内容来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

