(unnamed)

text/plain

Filename: (unnamed)
Type: text/plain
Part: 0
Message: Help with pg_locks query
-- 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);