提交 987113c9 编写于 作者: A Ashwin Agrawal

Avoid checkpoint between commit record and persistent post-commit.

The commit xlog record carries the information for objects which serves us for
crash-recovery till post-commit persistent object work is done, hence cannot
allow checkpoint in between. So, use inCommit flag to achieve the same. This
makes it consistent with FinishPreparedTransaction() as well.

Without the fix leaves out dangling persistent table entries and files on-disk
for following sequence:

- start transaction to drop a table
- `RecordTransactionCommit()`
- Checkpoint before `AtEOXact_smgr()`
- Crash/Recover
上级 43dd7315
...@@ -1324,8 +1324,6 @@ EndPrepare(GlobalTransaction gxact) ...@@ -1324,8 +1324,6 @@ EndPrepare(GlobalTransaction gxact)
/* Add the prepared record to our global list */ /* Add the prepared record to our global list */
add_recover_post_checkpoint_prepared_transactions_map_entry(xid, &gxact->prepare_begin_lsn, "EndPrepare"); add_recover_post_checkpoint_prepared_transactions_map_entry(xid, &gxact->prepare_begin_lsn, "EndPrepare");
MyProc->inCommit = true;
XLogFlush(gxact->prepare_lsn); XLogFlush(gxact->prepare_lsn);
/* /*
......
...@@ -1038,15 +1038,14 @@ AtSubStart_ResourceOwner(void) ...@@ -1038,15 +1038,14 @@ AtSubStart_ResourceOwner(void)
* *
* Returns latest XID among xact and its children, or InvalidTransactionId * Returns latest XID among xact and its children, or InvalidTransactionId
* if the xact has no XID. (We compute that here just because it's easier.) * if the xact has no XID. (We compute that here just because it's easier.)
*
* This is exported only to support an ugly hack in VACUUM FULL.
*/ */
TransactionId static TransactionId
RecordTransactionCommit(void) RecordTransactionCommit(void)
{ {
TransactionId xid; TransactionId xid;
bool markXidCommitted; bool markXidCommitted;
TransactionId latestXid = InvalidTransactionId; TransactionId latestXid = InvalidTransactionId;
bool save_inCommit;
MIRRORED_LOCK_DECLARE; MIRRORED_LOCK_DECLARE;
int32 persistentCommitSerializeLen; int32 persistentCommitSerializeLen;
...@@ -1164,6 +1163,7 @@ RecordTransactionCommit(void) ...@@ -1164,6 +1163,7 @@ RecordTransactionCommit(void)
* bit fuzzy, but it doesn't matter. * bit fuzzy, but it doesn't matter.
*/ */
START_CRIT_SECTION(); START_CRIT_SECTION();
save_inCommit = MyProc->inCommit;
MyProc->inCommit = true; MyProc->inCommit = true;
MIRRORED_LOCK; MIRRORED_LOCK;
...@@ -1370,7 +1370,7 @@ RecordTransactionCommit(void) ...@@ -1370,7 +1370,7 @@ RecordTransactionCommit(void)
*/ */
if (markXidCommitted) if (markXidCommitted)
{ {
MyProc->inCommit = false; MyProc->inCommit = save_inCommit;
END_CRIT_SECTION(); END_CRIT_SECTION();
MIRRORED_UNLOCK; MIRRORED_UNLOCK;
...@@ -3428,6 +3428,15 @@ CommitTransaction(void) ...@@ -3428,6 +3428,15 @@ CommitTransaction(void)
* and FileRepResyncManager_InResyncTransition() * and FileRepResyncManager_InResyncTransition()
*/ */
MIRRORED_LOCK; MIRRORED_LOCK;
/*
* Need to ensure the recording of the commit record and the
* persistent post-commit work will be done either before or after a
* checkpoint. The commit xlog record carries the information for
* objects which serves us for crash-recovery till post-commit
* persistent object work is done, hence cannot allow checkpoint in
* between.
*/
MyProc->inCommit = true;
} }
/* Prevent cancel/die interrupt while cleaning up */ /* Prevent cancel/die interrupt while cleaning up */
...@@ -3546,6 +3555,7 @@ CommitTransaction(void) ...@@ -3546,6 +3555,7 @@ CommitTransaction(void)
if (willHaveObjectsFromSmgr) if (willHaveObjectsFromSmgr)
{ {
MIRRORED_UNLOCK; MIRRORED_UNLOCK;
MyProc->inCommit = false;
} }
AtEOXact_MultiXact(); AtEOXact_MultiXact();
......
...@@ -247,7 +247,6 @@ extern void UnregisterXactCallbackOnce(XactCallback callback, void *arg); ...@@ -247,7 +247,6 @@ extern void UnregisterXactCallbackOnce(XactCallback callback, void *arg);
extern void RegisterSubXactCallback(SubXactCallback callback, void *arg); extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg); extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
extern TransactionId RecordTransactionCommit(void);
extern void RecordDistributedForgetCommitted(struct TMGXACT_LOG *gxact_log); extern void RecordDistributedForgetCommitted(struct TMGXACT_LOG *gxact_log);
extern bool RecordCrashTransactionAbortRecord( extern bool RecordCrashTransactionAbortRecord(
TransactionId xid, TransactionId xid,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册