Advertisement
daniilak

Untitled

Jun 2nd, 2022
1,001
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. WITH RECURSIVE l AS (
  2.   SELECT pid, locktype, granted,
  3.     array_position(ARRAY['AccessShare','RowShare','RowExclusive','ShareUpdateExclusive','Share','ShareRowExclusive','Exclusive','AccessExclusive'], left(mode,-4)) m,
  4.     ROW(locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid) obj FROM pg_locks
  5. ), pairs AS (
  6.   SELECT w.pid waiter, l.pid locker, l.obj, l.m
  7.     FROM l w JOIN l ON l.obj IS NOT DISTINCT FROM w.obj AND l.locktype=w.locktype AND NOT l.pid=w.pid AND l.granted
  8.    WHERE NOT w.granted
  9.      AND NOT EXISTS ( SELECT FROM l i WHERE i.pid=l.pid AND i.locktype=l.locktype AND i.obj IS NOT DISTINCT FROM l.obj AND i.m > l.m )
  10. ), leads AS (
  11.   SELECT o.locker, 1::int lvl, count(*) q, ARRAY[locker] track, false AS cycle FROM pairs o GROUP BY o.locker
  12.   UNION ALL
  13.   SELECT i.locker, leads.lvl+1, (SELECT count(*) FROM pairs q WHERE q.locker=i.locker), leads.track||i.locker, i.locker=ANY(leads.track)
  14.     FROM pairs i, leads WHERE i.waiter=leads.locker AND NOT cycle
  15. ), tree AS (
  16.   SELECT locker pid,locker dad,locker root,CASE WHEN cycle THEN track END dl, NULL::record obj,0 lvl,locker::text path,array_agg(locker) OVER () all_pids FROM leads o
  17.    WHERE (cycle AND NOT EXISTS (SELECT FROM leads i WHERE i.locker=ANY(o.track) AND (i.lvl>o.lvl OR i.q<o.q)))
  18.       OR (NOT cycle AND NOT EXISTS (SELECT FROM pairs WHERE waiter=o.locker) AND NOT EXISTS (SELECT FROM leads i WHERE i.locker=o.locker AND i.lvl<o.lvl))
  19.   UNION ALL
  20.   SELECT w.waiter pid,tree.pid,tree.root,CASE WHEN w.waiter=ANY(tree.dl) THEN tree.dl END,w.obj,tree.lvl+1,tree.path||'.'||w.waiter,all_pids || array_agg(w.waiter) OVER ()
  21.     FROM tree JOIN pairs w ON tree.pid=w.locker AND NOT w.waiter = ANY ( all_pids )
  22. )
  23. SELECT (clock_timestamp() - a.xact_start)::interval(0) AS ts_age,
  24.        (clock_timestamp() - a.state_change)::interval(0) AS change_age,
  25.        a.datname,a.usename,a.client_addr,
  26.        --w.obj wait_on_object,
  27.        tree.pid,replace(a.state, 'idle in transaction', 'idletx') state,
  28.        lvl,(SELECT count(*) FROM tree p WHERE p.path ~ ('^'||tree.path) AND NOT p.path=tree.path) blocked,
  29.        CASE WHEN tree.pid=ANY(tree.dl) THEN '!>' ELSE repeat(' .', lvl) END||' '||trim(left(regexp_replace(a.query, E'\\s+', ' ', 'g'),100)) query
  30.   FROM tree
  31.   LEFT JOIN pairs w ON w.waiter=tree.pid AND w.locker=tree.dad
  32.   JOIN pg_stat_activity a USING (pid)
  33.   JOIN pg_stat_activity r ON r.pid=tree.root
  34.  ORDER BY (now() - r.xact_start), path;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement