PostgreSQL employs diverse lock modes to manage concurrent data access in tables, complementing Multi-Version Concurrency Control (MVCC) when needed. These locks are automatically applied by most PostgreSQL commands to prevent conflicting operations on referenced tables during execution. For instance, TRUNCATE acquires an ACCESS EXCLUSIVE lock to ensure no concurrent operations interfere with it.
Additionally, applications can manually implement locks for specific requirements. The pg_locks system view allows users to monitor active locks in the database server, providing insight into the lock manager subsystem's status.
Today we I will explain about the Table-Level Locks mode in PostgreSQL
ACCESS SHARE (AccessShareLock):
- Conflicts with the ACCESS EXCLUSIVE lock mode only.
- The SELECT command acquires a lock of this mode on referenced tables. In general, any query that only reads a table and does not modify it will acquire this lock mode.
- Conflicts with the EXCLUSIVE and ACCESS EXCLUSIVE lock modes.
- The SELECT command acquires a lock of this mode on all tables on which one of the FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE, or FOR KEY SHARE options is specified (in addition to ACCESS SHARE locks on any other tables that are referenced without any explicit FOR ... locking option).
ROW EXCLUSIVE (RowExclusiveLock)
- Conflicts with the SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes.
- The commands UPDATE, DELETE, INSERT, and MERGE acquire this lock mode on the target table (in addition to ACCESS SHARE locks on any other referenced tables). In general, this lock mode will be acquired by any command that modifies data in a table.
SHARE UPDATE EXCLUSIVE (ShareUpdateExclusiveLock)
- Conflicts with the SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes. This mode protects a table against concurrent schema changes and VACUUM runs.
- Acquired by VACUUM (without FULL), ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, and certain ALTER INDEX and ALTER TABLE variants (for full details see the documentation of these commands).
- Conflicts with the ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes. This mode protects a table against concurrent data changes.
- Acquired by CREATE INDEX (without CONCURRENTLY).
SHARE ROW EXCLUSIVE (ShareRowExclusiveLock)
- Conflicts with the ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes. This mode protects a table against concurrent data changes, and is self-exclusive so that only one session can hold it at a time.
- Acquired by CREATE TRIGGER and some forms of ALTER TABLE.
EXCLUSIVE (ExclusiveLock)
- Conflicts with the ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes. This mode allows only concurrent ACCESS SHARE locks, i.e., only reads from the table can proceed in parallel with a transaction holding this lock mode.
- Acquired by REFRESH MATERIALIZED VIEW CONCURRENTLY.
ACCESS EXCLUSIVE (AccessExclusiveLock)
- Conflicts with locks of all modes (ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE). This mode guarantees that the holder is the only transaction accessing the table in any way.
- Acquired by the DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL, and REFRESH MATERIALIZED VIEW (without CONCURRENTLY) commands. Many forms of ALTER INDEX and ALTER TABLE also acquire a lock at this level. This is also the default lock mode for LOCK TABLE statements that do not specify a mode explicitly.
NOTE: Only an ACCESS EXCLUSIVE lock blocks a SELECT (without FOR UPDATE/SHARE) statement.