The view pg_locks provides access to information about the locks held by open transactions within the database server. See Chapter 13 for more discussion of locking.
pg_locks contains one row per active lockable object, requested lock mode, and relevant transaction. Thus, the same lockable object might appear many times, if multiple transactions are holding or waiting for locks on it. However, an object that currently has no locks on it will not appear at all.
There are several distinct types of lockable objects: whole relations (e.g., tables), individual pages of relations, individual tuples of relations, transaction IDs (both virtual and permanent IDs), and general database objects (identified by class OID and object OID, in the same way as in pg_description or pg_depend). Also, the right to extend a relation is represented as a separate lockable object. Also, "advisory" locks can be taken on numbers that have user-defined meanings.
Table 45-57. pg_locks Columns
|locktype||text||Type of the lockable object: relation, extend, page, tuple, transactionid, virtualxid, object, userlock, or advisory|
|database||oid||pg_database.oid||OID of the database in which the object exists, or zero if the object is a shared object, or null if the object is a transaction ID|
|relation||oid||pg_class.oid||OID of the relation, or null if the object is not a relation or part of a relation|
|page||integer||Page number within the relation, or null if the object is not a tuple or relation page|
|tuple||smallint||Tuple number within the page, or null if the object is not a tuple|
|virtualxid||text||Virtual ID of a transaction, or null if the object is not a virtual transaction ID|
|transactionid||xid||ID of a transaction, or null if the object is not a transaction ID|
|classid||oid||pg_class.oid||OID of the system catalog containing the object, or null if the object is not a general database object|
|objid||oid||any OID column||OID of the object within its system catalog, or null if the object is not a general database object|
|objsubid||smallint||Column number targeted by the lock (the classid and objid refer to the table itself), or zero if the target is some other general database object, or null if the target is not a general database object|
|virtualtransaction||text||Virtual ID of the transaction that is holding or awaiting this lock|
|pid||integer||Process ID of the server process holding or awaiting this lock, or null if the lock is held by a prepared transaction|
|mode||text||Name of the lock mode held or desired by this process (see Section 13.3.1 and Section 13.2.3)|
|granted||boolean||True if lock is held, false if lock is awaited|
granted is true in a row representing a lock held by the indicated transaction. False indicates that this transaction is currently waiting to acquire this lock, which implies that some other transaction is holding a conflicting lock mode on the same lockable object. The waiting transaction will sleep until the other lock is released (or a deadlock situation is detected). A single transaction can be waiting to acquire at most one lock at a time.
Every transaction holds an exclusive lock on its virtual transaction ID for its entire duration. If a permanent ID is assigned to the transaction (which normally happens only if the transaction changes the state of the database), it also holds an exclusive lock on its permanent transaction ID until it ends. When one transaction finds it necessary to wait specifically for another transaction, it does so by attempting to acquire share lock on the other transaction ID (either virtual or permanent ID depending on the situation). That will succeed only when the other transaction terminates and releases its locks.
Although tuples are a lockable type of object, information about row-level locks is stored on disk, not in memory, and therefore row-level locks normally do not appear in this view. If a transaction is waiting for a row-level lock, it will usually appear in the view as waiting for the permanent transaction ID of the current holder of that row lock.
Advisory locks can be acquired on keys consisting of either a single bigint value or two integer values. A bigint key is displayed with its high-order half in the classid column, its low-order half in the objid column, and objsubid equal to 1. Integer keys are displayed with the first key in the classid column, the second key in the objid column, and objsubid equal to 2. The actual meaning of the keys is up to the user. Advisory locks are local to each database, so the database column is meaningful for an advisory lock.
pg_locks provides a global view of all locks in the database cluster, not only those relevant to the current database. Although its relation column can be joined against pg_class.oid to identify locked relations, this will only work correctly for relations in the current database (those for which the database column is either the current database's OID or zero).
The pid column can be joined to the procpid column of the pg_stat_activity view to get more information on the session holding or waiting to hold each lock, for example
SELECT * FROM pg_locks pl LEFT JOIN pg_stat_activity psa ON pl.pid = psa.procpid;
Also, if you are using prepared transactions, the virtualtransaction column can be joined to the transaction column of the pg_prepared_xacts view to get more information on prepared transactions that hold locks. (A prepared transaction can never be waiting for a lock, but it continues to hold the locks it acquired while running.) For example:
SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx ON pl.virtualtransaction = '-1/' || ppx.transaction;
The pg_locks view displays data from both the regular lock manager and the predicate lock manager, which are separate systems. When this view is accessed, the internal data structures of each lock manager are momentarily locked, and copies are made for the view to display. Each lock manager will therefore produce a consistent set of results, but as we do not lock both lock managers simultaneously, it is possible for locks to be taken or released after we interrogate the regular lock manager and before we interrogate the predicate lock manager. Each lock manager is only locked for the minimum possible time so as to reduce the performance impact of querying this view, but there could nevertheless be some impact on database performance if it is frequently accessed.