From 66035734ec36e56e36d94f413f5eb7d498993b6d Mon Sep 17 00:00:00 2001 From: Simon Riggs Date: Wed, 12 May 2010 19:45:02 +0000 Subject: [PATCH] Give most recovery conflict errors a retryable error code. From recent requests and discussions with Yeb Havinga and Kevin Grittner. --- src/backend/tcop/postgres.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index b1d700a97e..4a08888561 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.593 2010/04/20 01:38:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.594 2010/05/12 19:45:02 sriggs Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -174,6 +174,7 @@ static int UseNewLine = 0; /* Use EOF as query delimiters */ /* whether or not, and why, we were cancelled by conflict with recovery */ static bool RecoveryConflictPending = false; +static bool RecoveryConflictRetryable = true; static ProcSignalReason RecoveryConflictReason; /* ---------------------------------------------------------------- @@ -2836,6 +2837,15 @@ RecoveryConflictInterrupt(ProcSignalReason reason) Assert(RecoveryConflictPending && (QueryCancelPending || ProcDiePending)); + /* + * All conflicts apart from database cause dynamic errors where the + * command or transaction can be retried at a later point with some + * potential for success. No need to reset this, since + * non-retryable conflict errors are currently FATAL. + */ + if (reason == PROCSIG_RECOVERY_CONFLICT_DATABASE) + RecoveryConflictRetryable = false; + /* * If it's safe to interrupt, and we're waiting for input or a lock, * service the interrupt immediately @@ -2885,6 +2895,11 @@ ProcessInterrupts(void) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating autovacuum process due to administrator command"))); + else if (RecoveryConflictPending && RecoveryConflictRetryable) + ereport(FATAL, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("terminating connection due to conflict with recovery"), + errdetail_recovery_conflict())); else if (RecoveryConflictPending) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), @@ -2936,14 +2951,14 @@ ProcessInterrupts(void) DisableCatchupInterrupt(); if (DoingCommandRead) ereport(FATAL, - (errcode(ERRCODE_ADMIN_SHUTDOWN), + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("terminating connection due to conflict with recovery"), errdetail_recovery_conflict(), errhint("In a moment you should be able to reconnect to the" " database and repeat your command."))); else ereport(ERROR, - (errcode(ERRCODE_QUERY_CANCELED), + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("canceling statement due to conflict with recovery"), errdetail_recovery_conflict())); } -- 2.40.0