Commit 66035734 authored by Simon Riggs's avatar Simon Riggs

Give most recovery conflict errors a retryable error code. From recent

requests and discussions with Yeb Havinga and Kevin Grittner.
parent 44e55690
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -174,6 +174,7 @@ static int UseNewLine = 0; /* Use EOF as query delimiters */ ...@@ -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 */ /* whether or not, and why, we were cancelled by conflict with recovery */
static bool RecoveryConflictPending = false; static bool RecoveryConflictPending = false;
static bool RecoveryConflictRetryable = true;
static ProcSignalReason RecoveryConflictReason; static ProcSignalReason RecoveryConflictReason;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -2836,6 +2837,15 @@ RecoveryConflictInterrupt(ProcSignalReason reason) ...@@ -2836,6 +2837,15 @@ RecoveryConflictInterrupt(ProcSignalReason reason)
Assert(RecoveryConflictPending && (QueryCancelPending || ProcDiePending)); 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, * If it's safe to interrupt, and we're waiting for input or a lock,
* service the interrupt immediately * service the interrupt immediately
...@@ -2885,6 +2895,11 @@ ProcessInterrupts(void) ...@@ -2885,6 +2895,11 @@ ProcessInterrupts(void)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN), (errcode(ERRCODE_ADMIN_SHUTDOWN),
errmsg("terminating autovacuum process due to administrator command"))); 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) else if (RecoveryConflictPending)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN), (errcode(ERRCODE_ADMIN_SHUTDOWN),
...@@ -2936,14 +2951,14 @@ ProcessInterrupts(void) ...@@ -2936,14 +2951,14 @@ ProcessInterrupts(void)
DisableCatchupInterrupt(); DisableCatchupInterrupt();
if (DoingCommandRead) if (DoingCommandRead)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN), (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("terminating connection due to conflict with recovery"), errmsg("terminating connection due to conflict with recovery"),
errdetail_recovery_conflict(), errdetail_recovery_conflict(),
errhint("In a moment you should be able to reconnect to the" errhint("In a moment you should be able to reconnect to the"
" database and repeat your command."))); " database and repeat your command.")));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_QUERY_CANCELED), (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("canceling statement due to conflict with recovery"), errmsg("canceling statement due to conflict with recovery"),
errdetail_recovery_conflict())); errdetail_recovery_conflict()));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment