Skip to content

Commit 7487a77

Browse files
committed
skip transactions and locks in other databases when checking pg_locks' entries
problem: in case there are open transactions on other databases then the one pg_repack is working on and pg_locks doesn't contain any information about the affected database oid of the locked relation (e.g. there is no locked relation, only an open transaction), pg_repack will wait for that connection to release the lock (even if the relation that gets reorganized is held in an different database). solution: join pg_database (via pg_stat_activity's datid) and check if the connection (of the conflicted transaction) is established on a different database than the relation treated by pg_repack and skip them. furthermore don't exclude transactions from other databases when shared objects are locked.
1 parent d1ab1f7 commit 7487a77

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

bin/pg_repack.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ const char *PROGRAM_VERSION = "unknown";
5959
* c. Other pg_repack clients, as distinguished by application_name, which
6060
* may be operating on other tables at the same time. See
6161
* https://github.com/reorg/pg_repack/issues/1
62+
* d. open transactions/locks existing on other databases than the actual
63+
* processing relation (except for locks on shared objects)
6264
*
6365
* Note, there is some redundancy in how the filtering is done (e.g. excluding
6466
* based on pg_backend_pid() and application_name), but that shouldn't hurt
@@ -71,28 +73,40 @@ const char *PROGRAM_VERSION = "unknown";
7173
" FROM pg_locks AS l " \
7274
" LEFT JOIN pg_stat_activity AS a " \
7375
" ON l.pid = a.pid " \
76+
" LEFT JOIN pg_database AS d " \
77+
" ON a.datid = d.oid " \
7478
" WHERE l.locktype = 'virtualxid' " \
7579
" AND l.pid NOT IN (pg_backend_pid(), $1) " \
7680
" AND (l.virtualxid, l.virtualtransaction) <> ('1/1', '-1/0') " \
77-
" AND (a.application_name IS NULL OR a.application_name <> $2)"
81+
" AND (a.application_name IS NULL OR a.application_name <> $2)" \
82+
" AND ((d.datname IS NULL OR d.datname = current_database()) OR l.database = 0)"
7883

7984
#define SQL_XID_SNAPSHOT_90000 \
8085
"SELECT repack.array_accum(l.virtualtransaction) " \
8186
" FROM pg_locks AS l " \
8287
" LEFT JOIN pg_stat_activity AS a " \
8388
" ON l.pid = a.procpid " \
89+
" LEFT JOIN pg_database AS d " \
90+
" ON a.datid = d.oid " \
8491
" WHERE l.locktype = 'virtualxid' " \
8592
" AND l.pid NOT IN (pg_backend_pid(), $1) " \
8693
" AND (l.virtualxid, l.virtualtransaction) <> ('1/1', '-1/0') " \
87-
" AND (a.application_name IS NULL OR a.application_name <> $2)"
94+
" AND (a.application_name IS NULL OR a.application_name <> $2)" \
95+
" AND ((d.datname IS NULL OR d.datname = current_database()) OR l.database = 0)"
8896

8997
/* application_name is not available before 9.0. The last clause of
9098
* the WHERE clause is just to eat the $2 parameter (application name).
9199
*/
92100
#define SQL_XID_SNAPSHOT_80300 \
93-
"SELECT repack.array_accum(virtualtransaction) FROM pg_locks" \
94-
" WHERE locktype = 'virtualxid' AND pid NOT IN (pg_backend_pid(), $1)" \
95-
" AND (virtualxid, virtualtransaction) <> ('1/1', '-1/0') " \
101+
"SELECT repack.array_accum(l.virtualtransaction) " \
102+
" FROM pg_locks AS l" \
103+
" LEFT JOIN pg_stat_activity AS a " \
104+
" ON l.pid = a.procpid " \
105+
" LEFT JOIN pg_database AS d " \
106+
" ON a.datid = d.oid " \
107+
" WHERE l.locktype = 'virtualxid' AND l.pid NOT IN (pg_backend_pid(), $1)" \
108+
" AND (l.virtualxid, l.virtualtransaction) <> ('1/1', '-1/0') " \
109+
" AND ((d.datname IS NULL OR d.datname = current_database()) OR l.database = 0)" \
96110
" AND ($2::text IS NOT NULL)"
97111

98112
#define SQL_XID_SNAPSHOT \

0 commit comments

Comments
 (0)