Skip to content

Commit a8ce974

Browse files
Teach standby conflict resolution to use SIGUSR1
Conflict reason is passed through directly to the backend, so we can take decisions about the effect of the conflict based upon the local state. No specific changes, as yet, though this prepares for later work. CancelVirtualTransaction() sends signals while holding ProcArrayLock. Introduce errdetail_abort() to give message detail explaining that the abort was caused by conflict processing. Remove CONFLICT_MODE states in favour of using PROCSIG_RECOVERY_CONFLICT states directly, for clarity.
1 parent c9dc53b commit a8ce974

File tree

11 files changed

+227
-153
lines changed

11 files changed

+227
-153
lines changed

src/backend/access/transam/xact.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.280 2010/01/09 16:49:27 sriggs Exp $
13+
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.281 2010/01/16 10:05:50 sriggs Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -313,8 +313,7 @@ IsTransactionState(void)
313313
/*
314314
* IsAbortedTransactionBlockState
315315
*
316-
* This returns true if we are currently running a query
317-
* within an aborted transaction block.
316+
* This returns true if we are within an aborted transaction block.
318317
*/
319318
bool
320319
IsAbortedTransactionBlockState(void)

src/backend/storage/ipc/procarray.c

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.55 2010/01/10 15:44:28 sriggs Exp $
40+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.56 2010/01/16 10:05:50 sriggs Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -324,6 +324,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
324324
/* must be cleared with xid/xmin: */
325325
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
326326
proc->inCommit = false; /* be sure this is cleared in abort */
327+
proc->recoveryConflictPending = false;
327328

328329
/* Clear the subtransaction-XID cache too while holding the lock */
329330
proc->subxids.nxids = 0;
@@ -350,6 +351,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
350351
/* must be cleared with xid/xmin: */
351352
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
352353
proc->inCommit = false; /* be sure this is cleared in abort */
354+
proc->recoveryConflictPending = false;
353355

354356
Assert(proc->subxids.nxids == 0);
355357
Assert(proc->subxids.overflowed == false);
@@ -377,7 +379,7 @@ ProcArrayClearTransaction(PGPROC *proc)
377379
proc->xid = InvalidTransactionId;
378380
proc->lxid = InvalidLocalTransactionId;
379381
proc->xmin = InvalidTransactionId;
380-
proc->recoveryConflictMode = 0;
382+
proc->recoveryConflictPending = false;
381383

382384
/* redundant, but just in case */
383385
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
@@ -1665,7 +1667,7 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid,
16651667
if (proc->pid == 0)
16661668
continue;
16671669

1668-
if (skipExistingConflicts && proc->recoveryConflictMode > 0)
1670+
if (skipExistingConflicts && proc->recoveryConflictPending)
16691671
continue;
16701672

16711673
if (!OidIsValid(dbOid) ||
@@ -1704,7 +1706,7 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid,
17041706
* Returns pid of the process signaled, or 0 if not found.
17051707
*/
17061708
pid_t
1707-
CancelVirtualTransaction(VirtualTransactionId vxid, int cancel_mode)
1709+
CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode)
17081710
{
17091711
ProcArrayStruct *arrayP = procArray;
17101712
int index;
@@ -1722,28 +1724,22 @@ CancelVirtualTransaction(VirtualTransactionId vxid, int cancel_mode)
17221724
if (procvxid.backendId == vxid.backendId &&
17231725
procvxid.localTransactionId == vxid.localTransactionId)
17241726
{
1725-
/*
1726-
* Issue orders for the proc to read next time it receives SIGINT
1727-
*/
1728-
if (proc->recoveryConflictMode < cancel_mode)
1729-
proc->recoveryConflictMode = cancel_mode;
1730-
1727+
proc->recoveryConflictPending = true;
17311728
pid = proc->pid;
1729+
if (pid != 0)
1730+
{
1731+
/*
1732+
* Kill the pid if it's still here. If not, that's what we wanted
1733+
* so ignore any errors.
1734+
*/
1735+
(void) SendProcSignal(pid, sigmode, vxid.backendId);
1736+
}
17321737
break;
17331738
}
17341739
}
17351740

17361741
LWLockRelease(ProcArrayLock);
17371742

1738-
if (pid != 0)
1739-
{
1740-
/*
1741-
* Kill the pid if it's still here. If not, that's what we wanted
1742-
* so ignore any errors.
1743-
*/
1744-
kill(pid, SIGINT);
1745-
}
1746-
17471743
return pid;
17481744
}
17491745

@@ -1834,6 +1830,7 @@ CancelDBBackends(Oid databaseid)
18341830
{
18351831
ProcArrayStruct *arrayP = procArray;
18361832
int index;
1833+
pid_t pid = 0;
18371834

18381835
/* tell all backends to die */
18391836
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
@@ -1844,8 +1841,21 @@ CancelDBBackends(Oid databaseid)
18441841

18451842
if (proc->databaseId == databaseid)
18461843
{
1847-
proc->recoveryConflictMode = CONFLICT_MODE_FATAL;
1848-
kill(proc->pid, SIGINT);
1844+
VirtualTransactionId procvxid;
1845+
1846+
GET_VXID_FROM_PGPROC(procvxid, *proc);
1847+
1848+
proc->recoveryConflictPending = true;
1849+
pid = proc->pid;
1850+
if (pid != 0)
1851+
{
1852+
/*
1853+
* Kill the pid if it's still here. If not, that's what we wanted
1854+
* so ignore any errors.
1855+
*/
1856+
(void) SendProcSignal(pid, PROCSIG_RECOVERY_CONFLICT_DATABASE,
1857+
procvxid.backendId);
1858+
}
18491859
}
18501860
}
18511861

src/backend/storage/ipc/procsignal.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procsignal.c,v 1.2 2010/01/02 16:57:51 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procsignal.c,v 1.3 2010/01/16 10:05:50 sriggs Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -24,6 +24,8 @@
2424
#include "storage/procsignal.h"
2525
#include "storage/shmem.h"
2626
#include "storage/sinval.h"
27+
#include "storage/standby.h"
28+
#include "tcop/tcopprot.h"
2729

2830

2931
/*
@@ -258,5 +260,17 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
258260
if (CheckProcSignal(PROCSIG_NOTIFY_INTERRUPT))
259261
HandleNotifyInterrupt();
260262

263+
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_DATABASE))
264+
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_DATABASE);
265+
266+
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_TABLESPACE))
267+
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_TABLESPACE);
268+
269+
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_LOCK))
270+
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_LOCK);
271+
272+
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT))
273+
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT);
274+
261275
errno = save_errno;
262276
}

src/backend/storage/ipc/standby.c

Lines changed: 12 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,15 @@
33
* standby.c
44
* Misc functions used in Hot Standby mode.
55
*
6-
* InitRecoveryTransactionEnvironment()
7-
* ShutdownRecoveryTransactionEnvironment()
8-
*
9-
* ResolveRecoveryConflictWithVirtualXIDs()
10-
*
116
* All functions for handling RM_STANDBY_ID, which relate to
127
* AccessExclusiveLocks and starting snapshots for Hot Standby mode.
8+
* Plus conflict recovery processing.
139
*
1410
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
1511
* Portions Copyright (c) 1994, Regents of the University of California
1612
*
1713
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.4 2010/01/14 11:08:02 sriggs Exp $
14+
* $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.5 2010/01/16 10:05:50 sriggs Exp $
1915
*
2016
*-------------------------------------------------------------------------
2117
*/
@@ -38,7 +34,7 @@ int vacuum_defer_cleanup_age;
3834
static List *RecoveryLockList;
3935

4036
static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
41-
char *reason, int cancel_mode);
37+
ProcSignalReason reason);
4238
static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid);
4339
static void LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
4440
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks);
@@ -162,17 +158,13 @@ WaitExceedsMaxStandbyDelay(void)
162158
* recovery processing. Judgement has already been passed on it within
163159
* a specific rmgr. Here we just issue the orders to the procs. The procs
164160
* then throw the required error as instructed.
165-
*
166-
* We may ask for a specific cancel_mode, typically ERROR or FATAL.
167161
*/
168162
static void
169163
ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
170-
char *reason, int cancel_mode)
164+
ProcSignalReason reason)
171165
{
172166
char waitactivitymsg[100];
173167

174-
Assert(cancel_mode > 0);
175-
176168
while (VirtualTransactionIdIsValid(*waitlist))
177169
{
178170
long wait_s;
@@ -206,12 +198,6 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
206198
len = 100;
207199
memcpy(waitactivitymsg, oldactivitymsg, len);
208200

209-
ereport(trace_recovery(DEBUG5),
210-
(errmsg("virtual transaction %u/%u is blocking %s",
211-
waitlist->backendId,
212-
waitlist->localTransactionId,
213-
reason)));
214-
215201
pgstat_report_waiting(true);
216202

217203
logged = true;
@@ -226,40 +212,14 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
226212
* Now find out who to throw out of the balloon.
227213
*/
228214
Assert(VirtualTransactionIdIsValid(*waitlist));
229-
pid = CancelVirtualTransaction(*waitlist, cancel_mode);
215+
pid = CancelVirtualTransaction(*waitlist, reason);
230216

217+
/*
218+
* Wait awhile for it to die so that we avoid flooding an
219+
* unresponsive backend when system is heavily loaded.
220+
*/
231221
if (pid != 0)
232-
{
233-
/*
234-
* Startup process debug messages
235-
*/
236-
switch (cancel_mode)
237-
{
238-
case CONFLICT_MODE_FATAL:
239-
elog(trace_recovery(DEBUG1),
240-
"recovery disconnects session with pid %ld because of conflict with %s",
241-
(long) pid,
242-
reason);
243-
break;
244-
case CONFLICT_MODE_ERROR:
245-
elog(trace_recovery(DEBUG1),
246-
"recovery cancels virtual transaction %u/%u pid %ld because of conflict with %s",
247-
waitlist->backendId,
248-
waitlist->localTransactionId,
249-
(long) pid,
250-
reason);
251-
break;
252-
default:
253-
/* No conflict pending, so fall through */
254-
break;
255-
}
256-
257-
/*
258-
* Wait awhile for it to die so that we avoid flooding an
259-
* unresponsive backend when system is heavily loaded.
260-
*/
261222
pg_usleep(5000);
262-
}
263223
}
264224
}
265225

@@ -285,8 +245,7 @@ ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid)
285245
true);
286246

287247
ResolveRecoveryConflictWithVirtualXIDs(backends,
288-
"snapshot conflict",
289-
CONFLICT_MODE_ERROR);
248+
PROCSIG_RECOVERY_CONFLICT_SNAPSHOT);
290249
}
291250

292251
void
@@ -317,8 +276,7 @@ ResolveRecoveryConflictWithTablespace(Oid tsid)
317276
InvalidOid,
318277
false);
319278
ResolveRecoveryConflictWithVirtualXIDs(temp_file_users,
320-
"drop tablespace",
321-
CONFLICT_MODE_ERROR);
279+
PROCSIG_RECOVERY_CONFLICT_TABLESPACE);
322280
}
323281

324282
void
@@ -379,8 +337,7 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid)
379337
}
380338

381339
ResolveRecoveryConflictWithVirtualXIDs(backends,
382-
"exclusive lock",
383-
CONFLICT_MODE_ERROR);
340+
PROCSIG_RECOVERY_CONFLICT_LOCK);
384341

385342
if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true, false)
386343
!= LOCKACQUIRE_NOT_AVAIL)

src/backend/storage/lmgr/proc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.212 2010/01/15 09:19:03 heikki Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.213 2010/01/16 10:05:50 sriggs Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -324,7 +324,7 @@ InitProcess(void)
324324
MyProc->waitProcLock = NULL;
325325
for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
326326
SHMQueueInit(&(MyProc->myProcLocks[i]));
327-
MyProc->recoveryConflictMode = 0;
327+
MyProc->recoveryConflictPending = false;
328328

329329
/*
330330
* We might be reusing a semaphore that belonged to a failed process. So

0 commit comments

Comments
 (0)