(unnamed)
text/plain
-- cannot be a temporary view because other sessions must see it
DROP VIEW IF EXISTS lockview CASCADE;
CREATE VIEW lockview AS
SELECT pid, virtualtransaction AS vxid, locktype AS lock_type,
mode AS lock_mode, granted,
CASE
WHEN virtualxid IS NOT NULL AND transactionid IS NOT NULL
THEN virtualxid || ' ' || transactionid
WHEN virtualxid::text IS NOT NULL
THEN virtualxid
ELSE transactionid::text
END AS xid_lock, relname,
page, tuple, classid, objid, objsubid
FROM pg_locks LEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid)
WHERE -- do not show our view's locks
pid != pg_backend_pid() AND
-- no need to show self-vxid locks
virtualtransaction IS DISTINCT FROM virtualxid
-- granted is ordered earlier
ORDER BY 1, 2, 5 DESC, 6, 3, 4, 7;
DROP VIEW IF EXISTS lockview1 CASCADE;
CREATE VIEW lockview1 AS
SELECT pid, vxid, lock_type, lock_mode, granted, xid_lock, relname
FROM lockview
-- granted is ordered earlier
ORDER BY 1, 2, 5 DESC, 6, 3, 4, 7;
DROP VIEW IF EXISTS lockview2 CASCADE;
CREATE VIEW lockview2 AS
SELECT pid, vxid, lock_type, page, tuple, classid, objid, objsubid
FROM lockview
-- granted is first
-- add non-display columns to match ordering of lockview
ORDER BY 1, 2, granted DESC, vxid, xid_lock::text, 3, 4, 5, 6, 7, 8;
DROP TABLE IF EXISTS lockdemo;
CREATE TABLE lockdemo (col int);
INSERT INTO lockdemo VALUES (1);
-- do two UPDATEs to cause a wait
CREATE VIEW lockinfo_hierarchy AS
WITH RECURSIVE lockinfo1 AS (
SELECT '1', pid, vxid, granted, xid_lock, lock_type, relname, page, tuple
FROM lockview
WHERE xid_lock IS NOT NULL AND
relname IS NULL AND
granted
UNION ALL
SELECT '2', lockview.pid, lockview.vxid, lockview.granted, lockview.xid_lock,
lockview.lock_type, lockview.relname, lockview.page, lockview.tuple
FROM lockinfo1 JOIN lockview ON (lockinfo1.xid_lock = lockview.xid_lock)
WHERE lockview.xid_lock IS NOT NULL AND
lockview.relname IS NULL AND
NOT lockview.granted AND
lockinfo1.granted),
lockinfo2 AS (
SELECT '3', pid, vxid, granted, xid_lock, lock_type, relname, page, tuple
FROM lockview
WHERE lock_type = 'tuple' AND
granted
UNION ALL
SELECT '4', lockview.pid, lockview.vxid, lockview.granted, lockview.xid_lock,
lockview.lock_type, lockview.relname, lockview.page, lockview.tuple
FROM lockinfo2 JOIN lockview ON (
lockinfo2.lock_type = lockview.lock_type AND
lockinfo2.relname = lockview.relname AND
lockinfo2.page = lockview.page AND
lockinfo2.tuple = lockview.tuple)
WHERE lockview.lock_type = 'tuple' AND
NOT lockview.granted AND
lockinfo2.granted
)
SELECT * FROM lockinfo1
UNION ALL
SELECT * FROM lockinfo2;
-- try several updates
BEGIN WORK;
SELECT ctid, xmin, * FROM lockdemo;
UPDATE lockdemo SET col = 4;
SELECT ctid, xmin, * FROM lockdemo;
SELECT pg_backend_pid();
SELECT txid_current();
\! psql -e -c 'BEGIN WORK; UPDATE lockdemo SET col = 5; SELECT pg_sleep(0.300); COMMIT;' | sed 's/^/\t/g' &
\! psql -e -c 'BEGIN WORK; UPDATE lockdemo SET col = 6; SELECT pg_sleep(0.300); COMMIT;' | sed 's/^/\t/g' &
\! psql -e -c 'BEGIN WORK; UPDATE lockdemo SET col = 7; SELECT pg_sleep(0.300); COMMIT;' | sed 's/^/\t/g' &
SELECT pg_sleep(0.100);
\! psql -e -c 'SELECT * FROM lockview1;' | sed 's/^/\t/g'
\! psql -e -c 'SELECT * FROM lockview2;' | sed 's/^/\t/g'
\! psql -e -c 'SELECT * FROM lockinfo_hierarchy;' | sed 's/^/\t/g'
\! psql -e -c 'SELECT * FROM pg_locks;' | sed 's/^/\t/g'
COMMIT;
\! psql -e -c 'SELECT * FROM lockview1;' | sed 's/^/\t/g'
\! psql -e -c 'SELECT * FROM lockview2;' | sed 's/^/\t/g'
SELECT pg_sleep(0.300);
DELETE FROM lockdemo;
INSERT INTO lockdemo VALUES (1);