mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
postgres_fdw: reestablish new connection if cached one is detected as broken.
In postgres_fdw, once remote connections are established, they are cached and re-used for subsequent queries and transactions. There can be some cases where those cached connections are unavaiable, for example, by the restart of remote server. In these cases, previously an error was reported and the query accessing to remote server failed if new remote transaction failed to start because the cached connection was broken. This commit improves postgres_fdw so that new connection is remade if broken connection is detected when starting new remote transaction. This is useful to avoid unnecessary failure of queries when connection is broken but can be reestablished. Author: Bharath Rupireddy, tweaked a bit by Fujii Masao Reviewed-by: Ashutosh Bapat, Tatsuhito Kasahara, Fujii Masao Discussion: https://postgr.es/m/CALj2ACUAi23vf1WiHNar_LksM9EDOWXcbHCo-fD4Mbr1d=78YQ@mail.gmail.com
This commit is contained in:
@ -2653,3 +2653,44 @@ SELECT count(*) FROM ft1;
|
||||
-- error here
|
||||
PREPARE TRANSACTION 'fdw_tpc';
|
||||
ROLLBACK;
|
||||
|
||||
-- ===================================================================
|
||||
-- reestablish new connection
|
||||
-- ===================================================================
|
||||
|
||||
-- Terminate the backend having the specified application_name and wait for
|
||||
-- the termination to complete.
|
||||
CREATE OR REPLACE PROCEDURE terminate_backend_and_wait(appname text) AS $$
|
||||
BEGIN
|
||||
PERFORM pg_terminate_backend(pid) FROM pg_stat_activity
|
||||
WHERE application_name = appname;
|
||||
LOOP
|
||||
PERFORM * FROM pg_stat_activity WHERE application_name = appname;
|
||||
EXIT WHEN NOT FOUND;
|
||||
PERFORM pg_sleep(1), pg_stat_clear_snapshot();
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Change application_name of remote connection to special one
|
||||
-- so that we can easily terminate the connection later.
|
||||
ALTER SERVER loopback OPTIONS (application_name 'fdw_retry_check');
|
||||
SELECT 1 FROM ft1 LIMIT 1;
|
||||
|
||||
-- Terminate the remote connection.
|
||||
CALL terminate_backend_and_wait('fdw_retry_check');
|
||||
|
||||
-- This query should detect the broken connection when starting new remote
|
||||
-- transaction, reestablish new connection, and then succeed.
|
||||
BEGIN;
|
||||
SELECT 1 FROM ft1 LIMIT 1;
|
||||
|
||||
-- If the query detects the broken connection when starting new remote
|
||||
-- subtransaction, it doesn't reestablish new connection and should fail.
|
||||
CALL terminate_backend_and_wait('fdw_retry_check');
|
||||
SAVEPOINT s;
|
||||
SELECT 1 FROM ft1 LIMIT 1; -- should fail
|
||||
COMMIT;
|
||||
|
||||
-- Clean up
|
||||
DROP PROCEDURE terminate_backend_and_wait(text);
|
||||
|
Reference in New Issue
Block a user