@@ -162,6 +162,31 @@ class PostgresInfo(object):
162162 '%-dead' , '%-heap-hit' , '%-idx-hit' )
163163 )
164164
165+ query_current_locks = ("""
166+ SELECT blocked_locks.pid AS blocked_pid,
167+ blocking_activity.datname as database,
168+ blocked_activity.usename AS blocked_user,
169+ blocking_locks.pid AS blocking_pid,
170+ blocking_activity.usename AS blocking_user,
171+ blocked_activity.query AS blocked_statement,
172+ coalesce((blocked_activity.state_change - now()), interval '0') AS duration
173+ FROM pg_catalog.pg_locks blocked_locks
174+ JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
175+ JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype
176+ AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
177+ AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
178+ AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
179+ AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
180+ AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
181+ AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
182+ AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
183+ AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
184+ AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
185+ AND blocking_locks.pid != blocked_locks.pid
186+ JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
187+ WHERE NOT blocked_locks.granted;
188+ """ , ("blocked pid" , "database" , "blocked user" , "blocking pid" , "blocking user" , "blocked statement" , "duration" ))
189+
165190 def __init__ (self , args ):
166191 self .args = args
167192 logging .info ('Test connection...' )
@@ -180,6 +205,8 @@ def __init__(self, args):
180205 self .dblist = self ._collect_query (self .QueryDBList )
181206 logging .info ('Collect biggest table...' )
182207 self .biggest_tables = self ._collect_biggest ()
208+ logging .info ('Collect locks info...' )
209+ self .locks = self ._collect_locks ()
183210
184211 def collect (self ):
185212 info = self .printable_info ()
@@ -225,6 +252,7 @@ def format_out(info, val):
225252 out += format_out ('PG SETTINGS' , format_obj (self .settings ))
226253 out += format_out ('PG DBLIST' , format_obj (self .dblist ))
227254 out += format_out ('TABLES LIST' , format_obj (self .biggest_tables ))
255+ out += format_out ('CURRENT LOCKS' , format_obj (self .locks ))
228256 return out
229257
230258 def printable_info (self ):
@@ -271,6 +299,25 @@ def format_out(key, val):
271299 for key in self .biggest_tables :
272300 out += key_val_h1 (
273301 key , self .biggest_tables [key ], 30 )
302+ for key in self .QueryPgSettings [2 ]:
303+ out += header_h1 (key )
304+ for row in self .settings :
305+ for name in self .QueryPgSettings [2 ][key ]:
306+ if row [0 ] == name :
307+ val = row [1 ]
308+ if row [2 ] is not None :
309+ val += ' {0}' .format (row [2 ])
310+ val = humansize (val )
311+ out += key_val_h1 (
312+ name , val , 30 )
313+ out += header_h1 ('Current Locks' )
314+ out += key_val_h1 (
315+ self .query_current_locks [1 ][0 ],
316+ "\t \t " + "\t \t " .join (self .query_current_locks [1 ][1 :]),
317+ 30 )
318+ for key in self .locks :
319+ out += key_val_h1 (
320+ key , self .locks [key ], 30 )
274321 return out
275322
276323 def _collect_query (self , query_desc ):
@@ -326,3 +373,19 @@ def _collect_biggest(self):
326373 for table_name in sorted (result , key = sizes .__getitem__ , reverse = True ):
327374 sorted_result [table_name ] = result [table_name ]
328375 return sorted_result
376+
377+ def _collect_locks (self ):
378+ result , pids , sorted_result = {}, {}, OrderedDict ({})
379+ try :
380+ for info in Pooler .query (self .query_current_locks [0 ]):
381+ blocked_pid = info [0 ]
382+ result [blocked_pid ] = ''
383+ values = info [1 :]
384+ pids [blocked_pid ] = values [- 1 ]
385+ for val in values :
386+ result [blocked_pid ] = "{0}\t \t {1}" .format (result [blocked_pid ], val )
387+ except Exception as e :
388+ logging .error ("Query locks error: {0}" .format (e ))
389+ for blocked_pid in sorted (result , key = pids .__getitem__ , reverse = True ):
390+ sorted_result [blocked_pid ] = result [blocked_pid ]
391+ return sorted_result
0 commit comments