mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Fix possible recovery trouble if TRUNCATE overlaps a checkpoint.
If TRUNCATE causes some buffers to be invalidated and thus the checkpoint does not flush them, TRUNCATE must also ensure that the corresponding files are truncated on disk. Otherwise, a replay from the checkpoint might find that the buffers exist but have the wrong contents, which may cause replay to fail. Report by Teja Mupparti. Patch by Kyotaro Horiguchi, per a design suggestion from Heikki Linnakangas, with some changes to the comments by me. Review of this and a prior patch that approached the issue differently by Heikki Linnakangas, Andres Freund, Álvaro Herrera, Masahiko Sawada, and Tom Lane. Discussion: http://postgr.es/m/BYAPR06MB6373BF50B469CA393C614257ABF00@BYAPR06MB6373.namprd06.prod.outlook.com
This commit is contained in:
@@ -698,7 +698,10 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
|
||||
|
||||
proc->lxid = InvalidLocalTransactionId;
|
||||
proc->xmin = InvalidTransactionId;
|
||||
proc->delayChkpt = false; /* be sure this is cleared in abort */
|
||||
|
||||
/* be sure this is cleared in abort */
|
||||
proc->delayChkpt = 0;
|
||||
|
||||
proc->recoveryConflictPending = false;
|
||||
|
||||
/* must be cleared with xid/xmin: */
|
||||
@@ -737,7 +740,10 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
|
||||
proc->xid = InvalidTransactionId;
|
||||
proc->lxid = InvalidLocalTransactionId;
|
||||
proc->xmin = InvalidTransactionId;
|
||||
proc->delayChkpt = false; /* be sure this is cleared in abort */
|
||||
|
||||
/* be sure this is cleared in abort */
|
||||
proc->delayChkpt = 0;
|
||||
|
||||
proc->recoveryConflictPending = false;
|
||||
|
||||
/* must be cleared with xid/xmin: */
|
||||
@@ -3053,7 +3059,8 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly)
|
||||
* delaying checkpoint because they have critical actions in progress.
|
||||
*
|
||||
* Constructs an array of VXIDs of transactions that are currently in commit
|
||||
* critical sections, as shown by having delayChkpt set in their PGPROC.
|
||||
* critical sections, as shown by having specified delayChkpt bits set in their
|
||||
* PGPROC.
|
||||
*
|
||||
* Returns a palloc'd array that should be freed by the caller.
|
||||
* *nvxids is the number of valid entries.
|
||||
@@ -3067,13 +3074,15 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly)
|
||||
* for clearing of delayChkpt to propagate is unimportant for correctness.
|
||||
*/
|
||||
VirtualTransactionId *
|
||||
GetVirtualXIDsDelayingChkpt(int *nvxids)
|
||||
GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
|
||||
{
|
||||
VirtualTransactionId *vxids;
|
||||
ProcArrayStruct *arrayP = procArray;
|
||||
int count = 0;
|
||||
int index;
|
||||
|
||||
Assert(type != 0);
|
||||
|
||||
/* allocate what's certainly enough result space */
|
||||
vxids = (VirtualTransactionId *)
|
||||
palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
|
||||
@@ -3085,7 +3094,7 @@ GetVirtualXIDsDelayingChkpt(int *nvxids)
|
||||
int pgprocno = arrayP->pgprocnos[index];
|
||||
PGPROC *proc = &allProcs[pgprocno];
|
||||
|
||||
if (proc->delayChkpt)
|
||||
if ((proc->delayChkpt & type) != 0)
|
||||
{
|
||||
VirtualTransactionId vxid;
|
||||
|
||||
@@ -3111,12 +3120,14 @@ GetVirtualXIDsDelayingChkpt(int *nvxids)
|
||||
* those numbers should be small enough for it not to be a problem.
|
||||
*/
|
||||
bool
|
||||
HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
|
||||
HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
|
||||
{
|
||||
bool result = false;
|
||||
ProcArrayStruct *arrayP = procArray;
|
||||
int index;
|
||||
|
||||
Assert(type != 0);
|
||||
|
||||
LWLockAcquire(ProcArrayLock, LW_SHARED);
|
||||
|
||||
for (index = 0; index < arrayP->numProcs; index++)
|
||||
@@ -3127,7 +3138,8 @@ HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
|
||||
|
||||
GET_VXID_FROM_PGPROC(vxid, *proc);
|
||||
|
||||
if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
|
||||
if ((proc->delayChkpt & type) != 0 &&
|
||||
VirtualTransactionIdIsValid(vxid))
|
||||
{
|
||||
int i;
|
||||
|
||||
|
Reference in New Issue
Block a user