From bad2fc14e284657bf32f783e608263c06a4b74c7 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko Date: Sun, 25 Jul 2021 17:50:49 +0300 Subject: [PATCH] Fix remote_txn_heal_data_node() for multiple DB's Since pg_prepared_xacts is shared between databases, the healing function tried to resolve prepared transactions created by other distributed databases. This change makes the healing function to work only with current database. Fix #3433 --- tsl/src/remote/txn_resolve.c | 25 +++++++++++++++--------- tsl/test/expected/remote_txn_resolve.out | 21 ++++++++++++++++++++ tsl/test/sql/remote_txn_resolve.sql | 18 +++++++++++++++++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/tsl/src/remote/txn_resolve.c b/tsl/src/remote/txn_resolve.c index 997616e64..8d1b316a9 100644 --- a/tsl/src/remote/txn_resolve.c +++ b/tsl/src/remote/txn_resolve.c @@ -28,15 +28,22 @@ remote_txn_resolution(Oid foreign_server, const RemoteTxnId *transaction_id) return REMOTE_TXN_RESOLUTION_ABORT; } -/* Resolve any unresolved 2-pc transaction on a data node. - Since the remote_txn log can be long, and most txn there - will have been resolved, do not iterate that list. - Instead query the data node for the list of unresolved txns - via the pg_prepared_xacts view. Using that list, then check - remote_txn. Use this as an opportunity to clean up remote_txn - as well. -*/ -#define GET_PREPARED_XACT_SQL "SELECT gid FROM pg_prepared_xacts" +/* + * Resolve any unresolved 2-pc transaction on a data node. + * Since the remote_txn log can be long, and most txn there + * will have been resolved, do not iterate that list. + * + * Instead query the data node for the list of unresolved txns + * via the pg_prepared_xacts view. Using that list, then check + * remote_txn. Use this as an opportunity to clean up remote_txn + * as well. + * + * Note that pg_prepared_xacts shared across other databases which + * also could be distributed. Right now we interested only in + * the current one. + */ +#define GET_PREPARED_XACT_SQL \ + "SELECT gid FROM pg_prepared_xacts WHERE database = current_database()" Datum remote_txn_heal_data_node(PG_FUNCTION_ARGS) diff --git a/tsl/test/expected/remote_txn_resolve.out b/tsl/test/expected/remote_txn_resolve.out index f689f8c47..d29c156d1 100644 --- a/tsl/test/expected/remote_txn_resolve.out +++ b/tsl/test/expected/remote_txn_resolve.out @@ -184,3 +184,24 @@ SELECT count(*) FROM _timescaledb_catalog.remote_txn; 0 (1 row) +-- test that healing function does not conflict with other databases +-- +-- #3433 +-- create additional database and simulate remote txn activity +CREATE DATABASE test_an2; +\c test_an2 +BEGIN; +CREATE TABLE unused(id int); +PREPARE TRANSACTION 'ts-1-10-20-30'; +\c :TEST_DBNAME :ROLE_SUPERUSER +-- should not fail +SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); + remote_txn_heal_data_node +--------------------------- + 0 +(1 row) + +\c test_an2 +ROLLBACK PREPARED 'ts-1-10-20-30'; +\c :TEST_DBNAME :ROLE_SUPERUSER +DROP DATABASE test_an2; diff --git a/tsl/test/sql/remote_txn_resolve.sql b/tsl/test/sql/remote_txn_resolve.sql index 512a7254a..07d77edaf 100644 --- a/tsl/test/sql/remote_txn_resolve.sql +++ b/tsl/test/sql/remote_txn_resolve.sql @@ -74,3 +74,21 @@ COMMIT PREPARED 'non-ts-txn'; SELECT * FROM table_modified_by_txns; SELECT count(*) FROM pg_prepared_xacts; SELECT count(*) FROM _timescaledb_catalog.remote_txn; + +-- test that healing function does not conflict with other databases +-- +-- #3433 + +-- create additional database and simulate remote txn activity +CREATE DATABASE test_an2; +\c test_an2 +BEGIN; +CREATE TABLE unused(id int); +PREPARE TRANSACTION 'ts-1-10-20-30'; +\c :TEST_DBNAME :ROLE_SUPERUSER +-- should not fail +SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); +\c test_an2 +ROLLBACK PREPARED 'ts-1-10-20-30'; +\c :TEST_DBNAME :ROLE_SUPERUSER +DROP DATABASE test_an2;