PostgreSQL aborts statements that wait too long for locks when lock_timeout is configured. Adjust the timeout value or resolve blocking queries to fix this error.
The "Lock timeout exceeded" error occurs when a PostgreSQL statement fails to acquire a lock within the time specified by the lock_timeout parameter. This parameter sets a maximum duration for waiting on locks (table locks, row locks, index locks, etc.). When a statement exceeds this wait time, PostgreSQL aborts it to prevent indefinite blocking. Unlike deadlock_timeout which checks for circular lock dependencies, lock_timeout simply enforces a wall-clock time limit on lock acquisition attempts.
Connect to your PostgreSQL database and view the current lock_timeout value:
SHOW lock_timeout;The default is 0 (disabled). If the value is non-zero, that setting is enforced.
Find which queries are holding locks and blocking others:
SELECT
blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS blocking_statement,
blocked_activity.application_name AS blocked_application,
blocking_activity.application_name AS blocking_application
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;This query shows which queries are blocked and which are causing the block.
If blocking queries are long-running and unnecessary, terminate them:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE pid != pg_backend_pid()
AND state = 'active'
AND query_start < NOW() - INTERVAL '30 minutes';Be cautious when terminating queries to avoid data corruption. Only terminate queries you own or have permission to terminate.
If the timeout is too aggressive for your workload, increase it at the session or role level:
SET lock_timeout = '30s';Or for a specific role:
ALTER ROLE myuser SET lock_timeout = '30s';Never set lock_timeout globally in postgresql.conf as it affects all sessions. Typical values range from 5-30 seconds depending on your workload.
Restructure transactions to minimize lock holding time:
- Move read-only queries outside locked transactions
- Use shorter transactions with focused operations
- Lock tables in consistent order across all transactions
- Use SELECT FOR UPDATE with appropriate lock levels
- Add indexes on frequently locked columns to reduce full table scans
Example of restructured transaction:
-- Bad: Long transaction holding locks
BEGIN;
SELECT * FROM large_table;
-- ... application processing ...
UPDATE small_table SET col = value;
COMMIT;
-- Good: Short transaction with lock
BEGIN;
UPDATE small_table SET col = value;
COMMIT;The lock_timeout parameter is different from deadlock_timeout and statement_timeout. The deadlock_timeout (default 1s) controls how long to wait before checking for deadlock conditions. The statement_timeout aborts entire statements after a time limit. For preventing long waits on locks, lock_timeout is the most direct solution. If you have statement_timeout set, ensure lock_timeout is not set to a larger value, as statement_timeout will trigger first. On heavily concurrent systems (many short transactions competing for same resources), consider increasing lock_timeout to allow legitimate wait times, while also investigating why locks are held so long. Row-level locking (SELECT FOR UPDATE) is generally preferable to table-level locking to reduce contention.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL