mirror of
https://gitee.com/he3db/he3pg.git
synced 2024-11-29 18:58:35 +08:00
fix pushstandby can't clean buffer when redo truncate wal
Signed-off-by: shipixian <shipixian_yewu@cmss.chinamobile.com>
This commit is contained in:
parent
6e00046003
commit
7dc5fd0303
@ -22,6 +22,7 @@
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "postmaster/bgwriter.h"
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
@ -385,6 +386,7 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
|
||||
Relation rel;
|
||||
ForkNumber fork;
|
||||
BlockNumber block;
|
||||
XLogRecPtr lsn = InvalidXLogRecPtr;
|
||||
|
||||
rel = relation_open(relid, AccessExclusiveLock);
|
||||
|
||||
@ -394,13 +396,6 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
|
||||
RelationOpenSmgr(rel);
|
||||
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber;
|
||||
|
||||
block = visibilitymap_prepare_truncate(rel, 0);
|
||||
if (BlockNumberIsValid(block))
|
||||
{
|
||||
fork = VISIBILITYMAP_FORKNUM;
|
||||
smgrtruncatelsn(rel->rd_smgr, &fork, 1, &block);
|
||||
}
|
||||
|
||||
if (RelationNeedsWAL(rel))
|
||||
{
|
||||
xl_smgr_truncate xlrec;
|
||||
@ -411,11 +406,36 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
|
||||
|
||||
XLogBeginInsert();
|
||||
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
|
||||
lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
|
||||
XLogFlush(lsn);
|
||||
if (IsBootstrapProcessingMode() != true && InitdbSingle != true) {
|
||||
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
|
||||
| CHECKPOINT_FLUSH_ALL);
|
||||
}
|
||||
XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
|
||||
}
|
||||
|
||||
block = visibilitymap_prepare_truncate(rel, 0);
|
||||
if (BlockNumberIsValid(block))
|
||||
{
|
||||
fork = VISIBILITYMAP_FORKNUM;
|
||||
/*
|
||||
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
|
||||
* just drop them without bothering to write the contents.
|
||||
*/
|
||||
DropRelFileNodeBuffers(rel->rd_smgr, &fork, 1, &block);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed, and/or
|
||||
* smgr_targblock variables pointing past the new rel end. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary local smgr flush. But we don't expect that this
|
||||
* is a performance-critical path.) As in the unlink code, we want to be
|
||||
* sure the message is sent before we start changing things on-disk.
|
||||
*/
|
||||
CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode);
|
||||
smgrtruncatelsn(rel->rd_smgr, &fork, 1, &block, lsn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/inval.h"
|
||||
#include "postmaster/bgwriter.h"
|
||||
|
||||
/* GUC variables */
|
||||
int wal_skip_threshold = 2048; /* in kilobytes */
|
||||
@ -283,6 +285,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
|
||||
ForkNumber forks[MAX_FORKNUM];
|
||||
BlockNumber blocks[MAX_FORKNUM];
|
||||
int nforks = 0;
|
||||
bool disable_cancel_query = false;
|
||||
|
||||
/* Open it at the smgr level if not already done */
|
||||
RelationOpenSmgr(rel);
|
||||
@ -344,16 +347,20 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
|
||||
|
||||
xl_smgr_truncate xlrec;
|
||||
|
||||
/*
|
||||
* He3DB: Disable cancel query during writing truacte XLOG and truncating.
|
||||
* If standby receive truncate log but master failed to trucate file,
|
||||
* standby will crash when master write to these blocks which truncated in standby node.
|
||||
*/
|
||||
HOLD_INTERRUPTS();
|
||||
disable_cancel_query = true;
|
||||
|
||||
xlrec.blkno = nblocks;
|
||||
xlrec.rnode = rel->rd_node;
|
||||
xlrec.flags = SMGR_TRUNCATE_ALL;
|
||||
|
||||
XLogBeginInsert();
|
||||
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
|
||||
if (IsBootstrapProcessingMode() != true && InitdbSingle != true) {
|
||||
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
|
||||
| CHECKPOINT_FLUSH_ALL);
|
||||
}
|
||||
lsn = XLogInsert(RM_SMGR_ID,
|
||||
XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
|
||||
|
||||
@ -366,10 +373,32 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
|
||||
*/
|
||||
if (fsm || vm)
|
||||
XLogFlush(lsn);
|
||||
|
||||
if (IsBootstrapProcessingMode() != true && InitdbSingle != true) {
|
||||
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
|
||||
| CHECKPOINT_FLUSH_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the real work to truncate relation forks */
|
||||
if (IsBootstrapProcessingMode()!=true && InitdbSingle!=true) {
|
||||
/*
|
||||
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
|
||||
* just drop them without bothering to write the contents.
|
||||
*/
|
||||
DropRelFileNodeBuffers(rel->rd_smgr, &forks, nforks, &blocks);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed, and/or
|
||||
* smgr_targblock variables pointing past the new rel end. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary local smgr flush. But we don't expect that this
|
||||
* is a performance-critical path.) As in the unlink code, we want to be
|
||||
* sure the message is sent before we start changing things on-disk.
|
||||
*/
|
||||
CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode);
|
||||
smgrtruncatelsn(rel->rd_smgr, forks, nforks, blocks,lsn);
|
||||
} else {
|
||||
smgrtruncate(rel->rd_smgr, forks, nforks, blocks);
|
||||
@ -383,6 +412,13 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
|
||||
*/
|
||||
if (need_fsm_vacuum)
|
||||
FreeSpaceMapVacuumRange(rel, nblocks, InvalidBlockNumber);
|
||||
|
||||
/* He3DB: Resume to enable cancel query */
|
||||
if (disable_cancel_query)
|
||||
{
|
||||
RESUME_INTERRUPTS();
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1010,6 +1046,24 @@ smgr_redo(XLogReaderState *record)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
|
||||
* just drop them without bothering to write the contents.
|
||||
*/
|
||||
DropRelFileNodeBuffers(reln, &forks, nforks, &blocks);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed, and/or
|
||||
* smgr_targblock variables pointing past the new rel end. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary local smgr flush. But we don't expect that this
|
||||
* is a performance-critical path.) As in the unlink code, we want to be
|
||||
* sure the message is sent before we start changing things on-disk.
|
||||
*/
|
||||
CacheInvalidateSmgr(reln->smgr_rnode);
|
||||
|
||||
/* Do the real work to truncate relation forks */
|
||||
if (nforks > 0 && (!EnableHotStandby || *isPromoteIsTriggered || !he3share))
|
||||
smgrtruncatelsn(reln, forks, nforks, blocks, record->ReadRecPtr);
|
||||
|
@ -1122,7 +1122,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
|
||||
pageTag.rnode = smgr->smgr_rnode.node;
|
||||
pageTag.forkNum = forkNum;
|
||||
pageTag.blockNum = blockNum;
|
||||
XLogRecPtr pageLsn = BufferGetLSN(bufHdr);
|
||||
// XLogRecPtr pageLsn = BufferGetLSN(bufHdr);
|
||||
XLogRecPtr pageLsn = Max(GetXLogPushToDisk(), BufferGetLSN(bufHdr));
|
||||
head = GetLogIndexByPage(&pageTag,pageLsn,replayLsn);
|
||||
if ((EnableHotStandby == true && *isPromoteIsTriggered == false) && push_standby == false) {
|
||||
if (head->next != NULL) {
|
||||
@ -1153,7 +1154,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
|
||||
pageTag.rnode = smgr->smgr_rnode.node;
|
||||
pageTag.forkNum = forkNum;
|
||||
pageTag.blockNum = blockNum;
|
||||
XLogRecPtr pageLsn = BufferGetLSN(bufHdr);
|
||||
// XLogRecPtr pageLsn = BufferGetLSN(bufHdr);
|
||||
XLogRecPtr pageLsn = Max(GetXLogPushToDisk(), BufferGetLSN(bufHdr));
|
||||
head = GetLogIndexByPage(&pageTag,pageLsn,replayLsn);
|
||||
if (head->next!=NULL) {
|
||||
LsnNode* next = head->next;
|
||||
|
@ -772,23 +772,7 @@ smgrtruncatelsn(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber
|
||||
int i;
|
||||
PageKey pk;
|
||||
OriginDPageKey odpk;
|
||||
/*
|
||||
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
|
||||
* just drop them without bothering to write the contents.
|
||||
*/
|
||||
DropRelFileNodeBuffers(reln, forknum, nforks, nblocks);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed, and/or
|
||||
* smgr_targblock variables pointing past the new rel end. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary local smgr flush. But we don't expect that this
|
||||
* is a performance-critical path.) As in the unlink code, we want to be
|
||||
* sure the message is sent before we start changing things on-disk.
|
||||
*/
|
||||
CacheInvalidateSmgr(reln->smgr_rnode);
|
||||
//push to truncate
|
||||
bool flag = false;
|
||||
/* Do the truncation */
|
||||
@ -801,7 +785,10 @@ smgrtruncatelsn(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber
|
||||
XLogRecPtr minApplyLsn;
|
||||
do {
|
||||
sleep(1);
|
||||
minApplyLsn = He3DBQueryMinLsnFromAllStanby();
|
||||
if (!EnableHotStandby || *isPromoteIsTriggered)
|
||||
minApplyLsn = QueryPushChkpointLsn();
|
||||
else
|
||||
minApplyLsn = He3DBQueryMinLsnFromAllStanby();
|
||||
elog(LOG,"====pushlsn=%lx==lsn==%lx==\n",minApplyLsn,lsn);
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
} while(minApplyLsn<lsn);
|
||||
|
Loading…
Reference in New Issue
Block a user