简体   繁体   中英

Delete statements locks table

Im running a cleanup job(every hour) on a table which constantly grows in rows.The job ran for about a week without any problems. Today i saw that the job started locking the entire table.

Is this expected behaviour ? Could it be that after a specific ammount of rows that need to be deleted it locks the entire table instead of only the specific rows that need to be deleted ?

Thanks in advance !

One possibility is that you need to index the column by which you are searching the table for rows to delete. If you do not have an index, then SQL Server will acquire many more locks while it searches for the rows to delete.

I highly recommend deleting small chunks of rows in a loop. As others have pointed out, if you try to delete more than about 5,000 rows at once, SQL Server will escalate the row locks into a table lock. Deleting fewer records at a time-- say, 1,000-- avoids locking the entire table. Your job can continue looping over the deletes until it is done.

The pseudocode for a looped delete looks like this:

declare @MoreRowsToDelete bit
set @MoreRowsToDelete = 1
while @MoreRowsToDelete = 1
begin
    delete top (1000) MyTable from MyTable where MyColumn = SomeCriteria
    if not exists (select top 1 * from MyTable where MyColumn = SomeCriteria)
        set @MoreRowsToDelete = 0
end

Alternatively, you could look at the @@ROWCOUNT and use READPAST hint to avoid locked rows:

declare @RowCount int
set @RowCount = 1 -- priming the loop
while @RowCount > 0
begin
    delete top (1000) MyTable from MyTable with (readpast) where MyColumn = SomeCriteria
    set @RowCount = @@ROWCOUNT
end

Note that the lock escalation threshold depends on other factors like concurrent activity. If you regularly have so much activity that even a 1,000 deletion will escalate to a table lock, you can lower the number of rows deleted at once.

If your query affects 5000 rows or more in the same table, that table gets locked during the operation. This is standard SQL Server behavior. Basically every DELETE causes a lock on that row and every 5000 row locks on the same table cause a Lock Escalation from row to table.

When you UPDATE / DELETE a row it gets locked (so far so easy), when there are many rows to be modified, the get locked one each till a certain point in time, where the DBMS 'decides' to switch to 'LOCK ENTIRE TABLE' As jean mentioned, this depends on many (and typically scaleable) paramaters of your DBMS and (typically) happens to get better performance.

But there is one bad thing with that: the chance to get "deadlocks" raises (I once had the problem with a mor or less 100% chance), because when the DBMS switches to "lock table" it has to wait for locks of other tasks on that table, but has it self (or your UOW) allready locked a few 1000 rows ...

To avoid this, sometimes it helps if you 'push' the DBMS a bit and lock the whole table (in exclusive mode) in advance. This helps if the UPDATE / DELETE it self modifies enough rows for Table locking to occure, but is still fast enough in it on world - what ever 'fast enough' in your environment means.

An other way to avoid this is delete / update only portions per query, if you are not dependig on the UOW (rollback), but this is typically not a problem with cleanups (if it gets rolled back, its part of the next cleanup, again), how to do that depends on your environment

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM