From 29023206b5713830ebd77f48cbfd18bf8dafc32f Mon Sep 17 00:00:00 2001 From: Josh Kupershmidt Date: Sun, 16 Jun 2013 20:17:24 -0400 Subject: [PATCH] Fix lock_exclusive()'s behavior during swap step. Since we are not starting a new transaction in conn2 during the swap step, we need to make sure that if our LOCK query is canceled due to statement_timeout that conn2's transaction is not left in a useless error state. Use SAVEPOINT and ROLLBACK TO SAVEPOINT to avoid this problem. --- bin/pg_repack.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/pg_repack.c b/bin/pg_repack.c index ea3fd2a..87de195 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -1404,7 +1404,9 @@ lock_access_share(PGconn *conn, Oid relid, const char *target_name) * conn: connection to use * relid: OID of relation * lock_query: LOCK TABLE ... IN ACCESS EXCLUSIVE query to be executed - * start_xact: whether we need to issue a BEGIN; + * start_xact: whether we will issue a BEGIN ourselves. If not, we will + * use a SAVEPOINT and ROLLBACK TO SAVEPOINT if our query + * times out, to avoid leaving the transaction in error state. */ static bool lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool start_xact) @@ -1422,6 +1424,8 @@ lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool sta if (start_xact) pgut_command(conn, "BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL); + else + pgut_command(conn, "SAVEPOINT repack_sp1", 0, NULL); duration = time(NULL) - start; if (duration > wait_timeout) @@ -1463,7 +1467,10 @@ lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool sta { /* retry if lock conflicted */ CLEARPGRES(res); - pgut_rollback(conn); + if (start_xact) + pgut_rollback(conn); + else + pgut_command(conn, "ROLLBACK TO SAVEPOINT repack_sp1", 0, NULL); continue; } else