Skip to content

Commit 1ea0225

Browse files
author
Baptiste Perbos
committed
wip: add blocking_activity_logger_verbose option, update output
1 parent d184638 commit 1ea0225

File tree

2 files changed

+58
-23
lines changed

2 files changed

+58
-23
lines changed

lib/safe-pg-migrations/configuration.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ module SafePgMigrations
66
class Configuration
77
attr_accessor :safe_timeout
88
attr_accessor :blocking_activity_logger_margin
9+
attr_accessor :blocking_activity_logger_verbose
910
attr_accessor :batch_size
1011
attr_accessor :retry_delay
1112
attr_accessor :max_tries
1213

1314
def initialize
1415
self.safe_timeout = 5.seconds
1516
self.blocking_activity_logger_margin = 1.second
17+
self.blocking_activity_logger_verbose = true
1618
self.batch_size = 1000
1719
self.retry_delay = 1.minute
1820
self.max_tries = 5

lib/safe-pg-migrations/plugins/blocking_activity_logger.rb

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,18 @@
22

33
module SafePgMigrations
44
module BlockingActivityLogger
5-
SELECT_BLOCKING_QUERIES_SQL = <<~SQL.squish
6-
SELECT blocking_activity.query, blocked_activity.xact_start as start
7-
FROM pg_catalog.pg_locks blocked_locks
8-
JOIN pg_catalog.pg_stat_activity blocked_activity
9-
ON blocked_activity.pid = blocked_locks.pid
10-
JOIN pg_catalog.pg_locks blocking_locks
11-
ON blocking_locks.locktype = blocked_locks.locktype
12-
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
13-
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
14-
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
15-
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
16-
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
17-
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
18-
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
19-
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
20-
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
21-
AND blocking_locks.pid != blocked_locks.pid
22-
JOIN pg_catalog.pg_stat_activity blocking_activity
23-
ON blocking_activity.pid = blocking_locks.pid
24-
WHERE blocked_locks.pid = %d
25-
SQL
5+
FILTERED_COLUMNS = %w(
6+
blocked_activity.xact_start
7+
blocked_locks.locktype
8+
blocked_locks.mode
9+
blocking_activity.pid
10+
blocked_locks.transactionid
11+
).freeze
12+
13+
VERBOSE_COLUMNS = %w(
14+
blocking_activity.query
15+
blocked_activity.xact_start
16+
).freeze
2617

2718
%i[
2819
add_column remove_column add_foreign_key remove_foreign_key change_column_default change_column_null create_table
@@ -34,14 +25,40 @@ module BlockingActivityLogger
3425

3526
private
3627

28+
def select_blocking_queries_sql
29+
columns = SafePgMigrations.config.blocking_activity_logger_verbose ? VERBOSE_COLUMNS : FILTERED_COLUMNS
30+
31+
<<~SQL.squish
32+
SELECT #{columns.join(', ')}
33+
FROM pg_catalog.pg_locks blocked_locks
34+
JOIN pg_catalog.pg_stat_activity blocked_activity
35+
ON blocked_activity.pid = blocked_locks.pid
36+
JOIN pg_catalog.pg_locks blocking_locks
37+
ON blocking_locks.locktype = blocked_locks.locktype
38+
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
39+
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
40+
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
41+
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
42+
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
43+
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
44+
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
45+
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
46+
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
47+
AND blocking_locks.pid != blocked_locks.pid
48+
JOIN pg_catalog.pg_stat_activity blocking_activity
49+
ON blocking_activity.pid = blocking_locks.pid
50+
WHERE blocked_locks.pid = %d
51+
SQL
52+
end
53+
3754
def log_blocking_queries
3855
delay_before_logging =
3956
SafePgMigrations.config.safe_timeout - SafePgMigrations.config.blocking_activity_logger_margin
4057

4158
blocking_queries_retriever_thread =
4259
Thread.new do
4360
sleep delay_before_logging
44-
SafePgMigrations.alternate_connection.query(SELECT_BLOCKING_QUERIES_SQL % raw_connection.backend_pid)
61+
SafePgMigrations.alternate_connection.query(select_blocking_queries_sql % raw_connection.backend_pid)
4562
end
4663

4764
yield
@@ -66,7 +83,7 @@ def log_blocking_queries
6683
"Statement was being blocked by the following #{'query'.pluralize(queries.size)}:", true
6784
)
6885
SafePgMigrations.say '', true
69-
queries.each { |query, start_time| SafePgMigrations.say "#{format_start_time start_time}: #{query}", true }
86+
output_blocking_queries(queries)
7087
SafePgMigrations.say(
7188
'Beware, some of those queries might run in a transaction. In this case the locking query might be '\
7289
'located elsewhere in the transaction',
@@ -78,6 +95,22 @@ def log_blocking_queries
7895
raise
7996
end
8097

98+
def output_blocking_queries(queries)
99+
if SafePgMigrations.config.blocking_activity_logger_verbose
100+
queries.each do |query, start_time|
101+
SafePgMigrations.say "#{format_start_time start_time}: #{query}", true
102+
end
103+
else
104+
queries.each do |start_time, locktype, mode, pid, transactionid|
105+
SafePgMigrations.say format_start_time(start_time), true
106+
SafePgMigrations.say "lock type: #{locktype || 'null'}"
107+
SafePgMigrations.say "lock mode: #{mode || 'null'}"
108+
SafePgMigrations.say "lock pid: #{pid || 'null'}"
109+
SafePgMigrations.say "lock transactionid: #{transactionid || 'null'}"
110+
end
111+
end
112+
end
113+
81114
def format_start_time(start_time, reference_time = Time.now)
82115
duration = (reference_time - start_time).round
83116
"transaction started #{duration} #{'second'.pluralize(duration)} ago"

0 commit comments

Comments
 (0)