Home SQL Server Errors 1222
Microsoft SQL Server

SQL Server Error 1222

Lock request time out period exceeded

Severity 16 Concurrency & Locking
Applies to: SQL Server 2005 to 2022, Azure SQL Database, Azure SQL Managed Instance
The full message
Msg 1222, Level 16, State 18, Line 1
Lock request time out period exceeded.

Why it happens

Error 1222 means your statement asked for a lock, could not get it in time, and stopped waiting. Every session has a LOCK_TIMEOUT value that sets the maximum time a statement will wait for a lock. When that time runs out, SQL Server abandons the wait and raises 1222 instead of blocking forever.

The real cause is almost always blocking: another session holds a lock inside an open transaction and has not committed or rolled back yet, so your statement cannot proceed. Unlike a deadlock (error 1205), nothing is chosen as a victim and killed to resolve the situation. Your statement simply times out on its own, and the blocking transaction keeps running.

This is severity 16, a normal, catchable error that points at a concurrency problem rather than a server fault. If you see it, some transaction elsewhere is holding a lock too long, or your LOCK_TIMEOUT is set very low. Find the blocker first, then decide whether to end it or raise the timeout.

Examples

A statement blocked by an uncommitted transaction

-- Session A: open a transaction and hold a lock, do not commit
BEGIN TRANSACTION;
UPDATE dbo.Accounts SET balance = balance - 100 WHERE id = 1;
-- (no COMMIT yet)

-- Session B: set a 3 second timeout, then try to read the locked row
SET LOCK_TIMEOUT 3000;
SELECT * FROM dbo.Accounts WHERE id = 1;  -- waits 3s, then errors
Result
Msg 1222, Level 16, State 18, Line 1
Lock request time out period exceeded.

A short timeout makes blocking surface immediately

-- With LOCK_TIMEOUT set low, any blocking fails fast
SET LOCK_TIMEOUT 500;
UPDATE dbo.Orders SET status = 'shipped' WHERE id = 42;
Result
Msg 1222, Level 16, State 18, Line 2
Lock request time out period exceeded.

How to fix it

Find the blocking session, then commit or kill it

The lasting fix is to deal with whatever holds the lock. Identify the blocker with the DMVs, then commit the blocking transaction or, if it is stuck, kill its session id. sp_who2 or the community script sp_whoisactive show the same information quickly.

-- Who is blocked and who is blocking them
SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time
FROM sys.dm_exec_requests AS r
WHERE r.blocking_session_id <> 0;

-- What locks are held
SELECT * FROM sys.dm_tran_locks;

-- Or use the built-in report
EXEC sp_who2;

-- Once identified, commit the blocker, or end it:
-- KILL 57;  -- replace 57 with the blocking_session_id

Keep transactions short so locks release faster

Locks are held until the transaction ends. Do only the necessary work between BEGIN TRANSACTION and COMMIT, and never wait on user input while a transaction is open. Shorter transactions release locks sooner and blocking rarely lasts long enough to time out.

BEGIN TRANSACTION;
UPDATE dbo.Accounts SET balance = balance - 100 WHERE id = 1;
UPDATE dbo.Accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;  -- commit right away, do not leave it open

Add indexes to shrink the lock footprint

A statement with no useful index scans and locks many more rows or pages than it needs. A supporting index lets SQL Server find and lock only the target rows, so it blocks fewer sessions and is blocked less often.

-- An index on the filtered column lets the UPDATE lock just its rows
CREATE INDEX IX_Orders_status ON dbo.Orders (status);

UPDATE dbo.Orders SET status = 'shipped' WHERE status = 'packed';

Let reads use snapshot rows instead of waiting

Turning on READ_COMMITTED_SNAPSHOT makes reads use a row version instead of taking a shared lock, so a SELECT no longer waits on writers and cannot hit 1222 while reading. This is one of the most effective ways to remove read-versus-write blocking.

ALTER DATABASE MyDb SET READ_COMMITTED_SNAPSHOT ON;
-- (run when you can get exclusive access to the database)

Raise or reset the timeout

If the wait is legitimate and you would rather wait than fail, raise LOCK_TIMEOUT or reset it. Setting it to -1 waits indefinitely, which is the default behavior. Treat this as a last resort after you understand the blocking, not a substitute for fixing it.

-- Wait up to 10 seconds
SET LOCK_TIMEOUT 10000;

-- Or restore the default: wait indefinitely
SET LOCK_TIMEOUT -1;

How to prevent it

Keep transactions short and commit promptly. The longer a transaction stays open, the longer it holds locks and the more likely another session waits past its timeout. Never leave a transaction open across user interaction or a slow external call. See the transactions, locks and deadlocks guide for how locking works.

Index the columns you filter and join on so statements lock only the rows they touch, and consider snapshot isolation (READ_COMMITTED_SNAPSHOT) so reads do not block on writers. Together, short transactions, good indexing, and snapshot reads remove most of the blocking that leads to 1222. For the concepts behind this, read SQL transactions and ACID explained.

Common questions

How do I fix SQL Server error 1222?

Find what is holding the lock and deal with it. Use sys.dm_exec_requests (blocking_session_id), sys.dm_tran_locks, or sp_who2 to identify the blocking session, then commit or kill it. Longer term, keep transactions short, add indexes, and consider READ_COMMITTED_SNAPSHOT so reads do not block. Raising LOCK_TIMEOUT only hides the problem.

What is the difference between error 1222 and error 1205?

They are both concurrency errors but different situations. Error 1205 is a deadlock, where two sessions block each other and SQL Server kills one as a victim to break the cycle. Error 1222 is a lock timeout, where your single statement waited longer than LOCK_TIMEOUT for a lock and gave up on its own. Nothing is killed to resolve 1222; the blocking transaction keeps running.

Does error 1222 mean SQL Server killed my query?

No. SQL Server did not choose your statement as a victim. Your statement waited for a lock, reached the LOCK_TIMEOUT limit, and stopped itself. The session that was blocking you is unaffected and continues to hold its lock until it commits or rolls back.

What does SET LOCK_TIMEOUT -1 do?

It tells the session to wait indefinitely for a lock, which is the default behavior. With that setting a blocked statement will never raise error 1222; it will simply wait until the lock is released. Use it only when waiting is acceptable and you understand why the blocking happens.

Still stuck on a SQL Server error?

Browse the full SQL Server error library, or get hands-on help from an experienced SQL professional.