diff --git a/README.md b/README.md index 857fea7..44163d6 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,6 @@ https://innovation.enova.com/pursuing-postgres-ddl-replication/ ### Release 1.6 Summary of changes: * Workaround pglogical 2.2.2 failure resulting from unstable `debug_query_string` results -* Support killing blockers on child tables while modifying parent -* Support killing blockers involved in fkey relationship * Add more tags as default for common use cases * Bug fix: Fix raise message escape % bug * Bug fix: Only auto-add tables to replication if CREATE TABLE tag configured diff --git a/expected/25_1_5_features.out b/expected/25_1_5_features.out index 9a4d1cc..e465c03 100644 --- a/expected/25_1_5_features.out +++ b/expected/25_1_5_features.out @@ -128,7 +128,6 @@ SELECT * FROM pgl_ddl_deploy.exceptions; CREATE TABLE public.foo(id serial primary key, bla int); CREATE TABLE public.foo2 () INHERITS (public.foo); -CREATE TABLE public.foo3 (id serial primary key, foo_id int references public.foo (id)); CREATE TABLE public.bar(id serial primary key, bla int); \! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo; SELECT pg_sleep(30);" > /dev/null 2>&1 & SELECT pg_sleep(1); @@ -317,53 +316,7 @@ FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo'); --------+------------+-------+-------+----------+---------- (0 rows) ***/ -/*** TEST FKEY RELATED TABLE BLOCKER KILLER ***/ --- Same workflow as above, but instead select from a table which has an fkey reference to foo.id -\! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo3; SELECT pg_sleep(30);" > /dev/null 2>&1 & -SELECT pg_sleep(1); - pg_sleep ----------- - -(1 row) - -SELECT signal, successful, state, query, reported, pg_sleep(1) -FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo'); - signal | successful | state | query | reported | pg_sleep ------------+------------+--------+--------------------------------------------------------+----------+---------- - terminate | t | active | BEGIN; SELECT * FROM public.foo3; SELECT pg_sleep(30); | f | -(1 row) - -/*** With <=1.5, it showed this. But it should kill the process. - signal | successful | state | query | reported | pg_sleep ---------+------------+-------+-------+----------+---------- -(0 rows) -***/ -/*** TEST REFERENCED BY TABLE BLOCKER KILLER ***/ --- Same workflow as above, but instead select from a table which has a pkey (foo) which is referenced by another table being altered (foo3) -\! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo; SELECT pg_sleep(30);" > /dev/null 2>&1 & -SELECT pg_sleep(1); - pg_sleep ----------- - -(1 row) - -SELECT signal, successful, state, query, reported, pg_sleep(1) -FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo3'); - signal | successful | state | query | reported | pg_sleep ------------+------------+--------+-------------------------------------------------------+----------+---------- - terminate | t | active | BEGIN; SELECT * FROM public.foo; SELECT pg_sleep(30); | f | -(1 row) - -/*** With <=1.5, it showed this. But it should kill the process. - signal | successful | state | query | reported | pg_sleep ---------+------------+-------+-------+----------+---------- -(0 rows) -***/ -SET lock_timeout TO 1000; DROP TABLE public.foo CASCADE; --- With <=1.5, lock is still in place leading to ERROR: canceling statement due to lock timeout -DROP TABLE public.foo3 CASCADE; --- With <=1.5, lock is still in place leading to ERROR: canceling statement due to lock timeout TABLE bar; id | bla ----+----- diff --git a/functions/kill_blockers.sql b/functions/kill_blockers.sql index 00dfa3f..e2077f5 100644 --- a/functions/kill_blockers.sql +++ b/functions/kill_blockers.sql @@ -71,14 +71,6 @@ INNER JOIN pg_stat_activity a on l.pid = a.pid LEFT JOIN pg_inherits pi ON pi.inhrelid = c.oid LEFT JOIN pg_class ipc on ipc.oid = pi.inhparent LEFT JOIN pg_namespace ipn on ipn.oid = ipc.relnamespace --- We need to check if there is a lock on a table with an fkey reference to this table -LEFT JOIN pg_constraint cr ON cr.conrelid = c.oid -LEFT JOIN pg_class crc ON crc.oid = cr.confrelid -LEFT JOIN pg_namespace crn ON crn.oid = crc.relnamespace --- We need to check if there is a lock on a table with a pkey that is referenced by this table -LEFT JOIN pg_constraint cf ON cf.confrelid = c.oid -LEFT JOIN pg_class cfc ON cfc.oid = cf.conrelid -LEFT JOIN pg_namespace cfn ON cfn.oid = cfc.relnamespace -- We do not exclude either postgres user or pglogical processes, because we even want to cancel autovac blocks. -- It should not be possible to contend with pglogical write processes (at least as of pglogical 2.2), because -- these run single-threaded using the same process that is doing the DDL and already holds any lock it needs @@ -87,9 +79,7 @@ WHERE NOT a.pid = pg_backend_pid() -- both nspname and relname will be an empty string, thus a no-op, if for some reason one or the other -- is not found on the provider side in pg_event_trigger_ddl_commands(). This is a safety mechanism! AND ((n.nspname = p_nspname AND c.relname = p_relname) -OR (ipn.nspname = p_nspname AND ipc.relname = p_relname) -OR (crn.nspname = p_nspname AND crc.relname = p_relname) -OR (cfn.nspname = p_nspname AND cfc.relname = p_relname)) +OR (ipn.nspname = p_nspname AND ipc.relname = p_relname)) AND a.datname = current_database() AND c.relkind = 'r' AND l.locktype = 'relation' diff --git a/pgl_ddl_deploy--1.5--1.6.sql b/pgl_ddl_deploy--1.5--1.6.sql index 5d97ce2..b3539db 100644 --- a/pgl_ddl_deploy--1.5--1.6.sql +++ b/pgl_ddl_deploy--1.5--1.6.sql @@ -100,14 +100,6 @@ INNER JOIN pg_stat_activity a on l.pid = a.pid LEFT JOIN pg_inherits pi ON pi.inhrelid = c.oid LEFT JOIN pg_class ipc on ipc.oid = pi.inhparent LEFT JOIN pg_namespace ipn on ipn.oid = ipc.relnamespace --- We need to check if there is a lock on a table with an fkey reference to this table -LEFT JOIN pg_constraint cr ON cr.conrelid = c.oid -LEFT JOIN pg_class crc ON crc.oid = cr.confrelid -LEFT JOIN pg_namespace crn ON crn.oid = crc.relnamespace --- We need to check if there is a lock on a table with a pkey that is referenced by this table -LEFT JOIN pg_constraint cf ON cf.confrelid = c.oid -LEFT JOIN pg_class cfc ON cfc.oid = cf.conrelid -LEFT JOIN pg_namespace cfn ON cfn.oid = cfc.relnamespace -- We do not exclude either postgres user or pglogical processes, because we even want to cancel autovac blocks. -- It should not be possible to contend with pglogical write processes (at least as of pglogical 2.2), because -- these run single-threaded using the same process that is doing the DDL and already holds any lock it needs @@ -116,9 +108,7 @@ WHERE NOT a.pid = pg_backend_pid() -- both nspname and relname will be an empty string, thus a no-op, if for some reason one or the other -- is not found on the provider side in pg_event_trigger_ddl_commands(). This is a safety mechanism! AND ((n.nspname = p_nspname AND c.relname = p_relname) -OR (ipn.nspname = p_nspname AND ipc.relname = p_relname) -OR (crn.nspname = p_nspname AND crc.relname = p_relname) -OR (cfn.nspname = p_nspname AND cfc.relname = p_relname)) +OR (ipn.nspname = p_nspname AND ipc.relname = p_relname)) AND a.datname = current_database() AND c.relkind = 'r' AND l.locktype = 'relation' diff --git a/pgl_ddl_deploy--1.6.sql b/pgl_ddl_deploy--1.6.sql index 5a246dd..5b2436b 100644 --- a/pgl_ddl_deploy--1.6.sql +++ b/pgl_ddl_deploy--1.6.sql @@ -5938,14 +5938,6 @@ INNER JOIN pg_stat_activity a on l.pid = a.pid LEFT JOIN pg_inherits pi ON pi.inhrelid = c.oid LEFT JOIN pg_class ipc on ipc.oid = pi.inhparent LEFT JOIN pg_namespace ipn on ipn.oid = ipc.relnamespace --- We need to check if there is a lock on a table with an fkey reference to this table -LEFT JOIN pg_constraint cr ON cr.conrelid = c.oid -LEFT JOIN pg_class crc ON crc.oid = cr.confrelid -LEFT JOIN pg_namespace crn ON crn.oid = crc.relnamespace --- We need to check if there is a lock on a table with a pkey that is referenced by this table -LEFT JOIN pg_constraint cf ON cf.confrelid = c.oid -LEFT JOIN pg_class cfc ON cfc.oid = cf.conrelid -LEFT JOIN pg_namespace cfn ON cfn.oid = cfc.relnamespace -- We do not exclude either postgres user or pglogical processes, because we even want to cancel autovac blocks. -- It should not be possible to contend with pglogical write processes (at least as of pglogical 2.2), because -- these run single-threaded using the same process that is doing the DDL and already holds any lock it needs @@ -5954,9 +5946,7 @@ WHERE NOT a.pid = pg_backend_pid() -- both nspname and relname will be an empty string, thus a no-op, if for some reason one or the other -- is not found on the provider side in pg_event_trigger_ddl_commands(). This is a safety mechanism! AND ((n.nspname = p_nspname AND c.relname = p_relname) -OR (ipn.nspname = p_nspname AND ipc.relname = p_relname) -OR (crn.nspname = p_nspname AND crc.relname = p_relname) -OR (cfn.nspname = p_nspname AND cfc.relname = p_relname)) +OR (ipn.nspname = p_nspname AND ipc.relname = p_relname)) AND a.datname = current_database() AND c.relkind = 'r' AND l.locktype = 'relation' diff --git a/sql/25_1_5_features.sql b/sql/25_1_5_features.sql index 7bdde93..199a312 100644 --- a/sql/25_1_5_features.sql +++ b/sql/25_1_5_features.sql @@ -65,7 +65,6 @@ SELECT * FROM pgl_ddl_deploy.exceptions; CREATE TABLE public.foo(id serial primary key, bla int); CREATE TABLE public.foo2 () INHERITS (public.foo); -CREATE TABLE public.foo3 (id serial primary key, foo_id int references public.foo (id)); CREATE TABLE public.bar(id serial primary key, bla int); \! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo; SELECT pg_sleep(30);" > /dev/null 2>&1 & SELECT pg_sleep(1); @@ -187,35 +186,7 @@ FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo'); (0 rows) ***/ -/*** TEST FKEY RELATED TABLE BLOCKER KILLER ***/ --- Same workflow as above, but instead select from a table which has an fkey reference to foo.id -\! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo3; SELECT pg_sleep(30);" > /dev/null 2>&1 & -SELECT pg_sleep(1); -SELECT signal, successful, state, query, reported, pg_sleep(1) -FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo'); -/*** With <=1.5, it showed this. But it should kill the process. - signal | successful | state | query | reported | pg_sleep ---------+------------+-------+-------+----------+---------- -(0 rows) -***/ - -/*** TEST REFERENCED BY TABLE BLOCKER KILLER ***/ --- Same workflow as above, but instead select from a table which has a pkey (foo) which is referenced by another table being altered (foo3) -\! PGOPTIONS='--client-min-messages=warning' psql -d contrib_regression -c "BEGIN; SELECT * FROM public.foo; SELECT pg_sleep(30);" > /dev/null 2>&1 & -SELECT pg_sleep(1); -SELECT signal, successful, state, query, reported, pg_sleep(1) -FROM pgl_ddl_deploy.kill_blockers('terminate','public','foo3'); -/*** With <=1.5, it showed this. But it should kill the process. - signal | successful | state | query | reported | pg_sleep ---------+------------+-------+-------+----------+---------- -(0 rows) -***/ - -SET lock_timeout TO 1000; DROP TABLE public.foo CASCADE; --- With <=1.5, lock is still in place leading to ERROR: canceling statement due to lock timeout -DROP TABLE public.foo3 CASCADE; --- With <=1.5, lock is still in place leading to ERROR: canceling statement due to lock timeout TABLE bar; DROP TABLE public.bar CASCADE;