Skip to content

Commit acc9ddb

Browse files
committed
feature: added Current Locks to report tool
1 parent 55901a5 commit acc9ddb

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

mamonsu/tools/report/pgsql.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
""", ("database", "blocked pid", "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

Comments
 (0)