提交 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)
/* Add the prepared record to our global list */
add_recover_post_checkpoint_prepared_transactions_map_entry(xid, &gxact->prepare_begin_lsn, "EndPrepare");
MyProc->inCommit = true;
XLogFlush(gxact->prepare_lsn);
/*
......
......@@ -1038,15 +1038,14 @@ AtSubStart_ResourceOwner(void)
*
* 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.)
*
* This is exported only to support an ugly hack in VACUUM FULL.
*/
TransactionId
static TransactionId
RecordTransactionCommit(void)
{
TransactionId xid;
bool markXidCommitted;
TransactionId latestXid = InvalidTransactionId;
bool save_inCommit;
MIRRORED_LOCK_DECLARE;
int32 persistentCommitSerializeLen;
......@@ -1164,6 +1163,7 @@ RecordTransactionCommit(void)
* bit fuzzy, but it doesn't matter.
*/
START_CRIT_SECTION();
save_inCommit = MyProc->inCommit;
MyProc->inCommit = true;
MIRRORED_LOCK;
......@@ -1370,7 +1370,7 @@ RecordTransactionCommit(void)
*/
if (markXidCommitted)
{
MyProc->inCommit = false;
MyProc->inCommit = save_inCommit;
END_CRIT_SECTION();
MIRRORED_UNLOCK;
......@@ -3428,6 +3428,15 @@ CommitTransaction(void)
* and FileRepResyncManager_InResyncTransition()
*/
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 */
......@@ -3546,6 +3555,7 @@ CommitTransaction(void)
if (willHaveObjectsFromSmgr)
{
MIRRORED_UNLOCK;
MyProc->inCommit = false;
}
AtEOXact_MultiXact();
......
......@@ -247,7 +247,6 @@ extern void UnregisterXactCallbackOnce(XactCallback callback, void *arg);
extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
extern TransactionId RecordTransactionCommit(void);
extern void RecordDistributedForgetCommitted(struct TMGXACT_LOG *gxact_log);
extern bool RecordCrashTransactionAbortRecord(
TransactionId xid,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册