udatapp_development=# begin;
BEGIN
udatapp_development=# lock table users in access exclusive mode;
LOCK TABLE
udatapp_development=#
udatapp_development=# begin; UPDATE users SET email = '[email protected]' WHERE id = 2;
BEGIN
udatapp_development=# SELECT locktype, relation::regclass, mode, transactionid AS tid,
virtualtransaction AS vtid, pid, granted
FROM pg_catalog.pg_locks l LEFT JOIN pg_catalog.pg_database db
ON db.oid = l.database WHERE (db.datname = 'udatapp_development' OR db.datname IS NULL)
AND NOT pid = pg_backend_pid();
locktype | relation | mode | tid | vtid | pid | granted
---------------+----------+---------------------+--------+---------+---------+---------
virtualxid | | ExclusiveLock | | 6/1333 | 3350240 | t
virtualxid | | ExclusiveLock | | 5/20859 | 3350531 | t
relation | users | RowExclusiveLock | | 6/1333 | 3350240 | f
relation | users | AccessExclusiveLock | | 5/20859 | 3350531 | t
transactionid | | ExclusiveLock | 818650 | 5/20859 | 3350531 | t
(5 rows)
But there is no transactionid
, so it is empty:
udatapp_development=# SELECT blockeda.pid AS blocked_pid, blockeda.query as blocked_query,
blockinga.pid AS blocking_pid, blockinga.query as blocking_query
FROM pg_catalog.pg_locks blockedl
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid
JOIN pg_catalog.pg_locks blockingl ON(blockingl.transactionid=blockedl.transactionid
AND blockedl.pid != blockingl.pid)
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid
WHERE NOT blockedl.granted AND blockinga.datname='udatapp_development';
blocked_pid | blocked_query | blocking_pid | blocking_query
-------------+---------------+--------------+----------------
(0 rows)
We can check the query duration:
udatapp_development=# SELECT pid, query, now() - query_start AS waiting_duration
FROM pg_catalog.pg_stat_activity WHERE datname='udatapp_development';
pid | query | waiting_duration
---------+-----------------------------------------------------------------------+------------------------
3350531 | lock table users in access exclusive mode; | 00:02:26.592682
3350240 | UPDATE users SET email = '[email protected]' WHERE id = 2; | 00:01:46.382441
3351199 | SELECT pid, query, now() - query_start AS waiting_duration +| 00:00:00
| FROM pg_catalog.pg_stat_activity WHERE datname='udatapp_development'; |
(5 rows)
Let's join the relation on which the lock is hold:
udatapp_development=# SELECT blockingl.relation::regclass,
blockeda.pid AS blocked_pid, blockeda.query as blocked_query,
blockedl.mode as blocked_mode,
blockinga.pid AS blocking_pid, blockinga.query as blocking_query,
blockingl.mode as blocking_mode
FROM pg_catalog.pg_locks blockedl
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid
JOIN pg_catalog.pg_locks blockingl ON(blockingl.relation=blockedl.relation
AND blockingl.locktype=blockedl.locktype AND blockedl.pid != blockingl.pid)
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid
WHERE NOT blockedl.granted AND blockinga.datname='udatapp_development';
relation | blocked_pid | blocked_query | blocked_mode | blocking_pid | blocking_query | blocking_mode
----------+-------------+--------------------------------------------------------------------+------------------+--------------+--------------------------------------------+---------------------
users | 3350240 | UPDATE users SET email = '[email protected]' WHERE id = 2; | RowExclusiveLock | 3350531 | lock table users in access exclusive mode; | AccessExclusiveLock
(1 row)
Commit transaction:
udatapp_development=# commit;
COMMIT
We see that update is completed and we are still inside the transaction:
udatapp_development=# begin; UPDATE users SET email = '[email protected]' WHERE id = 2;
BEGIN
UPDATE 1
So, the real transactionid has been added:
udatapp_development=# SELECT locktype, relation::regclass, mode, transactionid AS tid,
virtualtransaction AS vtid, pid, granted
FROM pg_catalog.pg_locks l LEFT JOIN pg_catalog.pg_database db
ON db.oid = l.database WHERE (db.datname = 'udatapp_development' OR db.datname IS NULL)
AND NOT pid = pg_backend_pid();
locktype | relation | mode | tid | vtid | pid | granted
---------------+----------------------+------------------+--------+--------+---------+---------
relation | index_users_on_email | RowExclusiveLock | | 6/1333 | 3350240 | t
relation | users_pkey | RowExclusiveLock | | 6/1333 | 3350240 | t
virtualxid | | ExclusiveLock | | 6/1333 | 3350240 | t
relation | users | RowExclusiveLock | | 6/1333 | 3350240 | t
transactionid | | ExclusiveLock | 818651 | 6/1333 | 3350240 | t
(5 rows)
Let's commit transaction in the 2nd console:
udatapp_development=# commit;
COMMIT
udatapp_development=# SELECT locktype, relation::regclass, mode, transactionid AS tid,
virtualtransaction AS vtid, pid, granted
FROM pg_catalog.pg_locks l LEFT JOIN pg_catalog.pg_database db
ON db.oid = l.database WHERE (db.datname = 'udatapp_development' OR db.datname IS NULL)
AND NOT pid = pg_backend_pid();
locktype | relation | mode | tid | vtid | pid | granted
----------+----------+------+-----+------+-----+---------
(0 rows)
Explanation link to see more information.