!1056 同步lsn check例外场景:truncate之后再init出来的page,不做检查
Merge pull request !1056 from mujinqiang/master0626
This commit is contained in:
@ -2191,7 +2191,7 @@ void xlog_db_create(Oid dstDbId, Oid dstTbSpcId, Oid srcDbId, Oid srcTbSpcId)
|
|||||||
RelFileNode tmp = {srcTbSpcId, srcDbId, 0, InvalidBktId};
|
RelFileNode tmp = {srcTbSpcId, srcDbId, 0, InvalidBktId};
|
||||||
|
|
||||||
/* forknum and blockno has no meaning */
|
/* forknum and blockno has no meaning */
|
||||||
log_invalid_page(tmp, MAIN_FORKNUM, 0, false);
|
log_invalid_page(tmp, MAIN_FORKNUM, 0, NOT_PRESENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,9 @@ void DoLsnCheck(RedoBufferInfo *bufferinfo, bool willInit, XLogRecPtr lastLsn)
|
|||||||
"lsn in current page %lu, page info:%u/%u/%u forknum %d lsn %lu blknum:%u",
|
"lsn in current page %lu, page info:%u/%u/%u forknum %d lsn %lu blknum:%u",
|
||||||
lastLsn, pageCurLsn, blockinfo->rnode.spcNode, blockinfo->rnode.dbNode,
|
lastLsn, pageCurLsn, blockinfo->rnode.spcNode, blockinfo->rnode.dbNode,
|
||||||
blockinfo->rnode.relNode, blockinfo->forknum, lsn, blockinfo->blkno)));
|
blockinfo->rnode.relNode, blockinfo->forknum, lsn, blockinfo->blkno)));
|
||||||
|
} else if (pageCurLsn == InvalidXLogRecPtr && PageIsEmpty(page) && PageUpperIsInitNew(page)) {
|
||||||
|
log_invalid_page(bufferinfo->blockinfo.rnode, bufferinfo->blockinfo.forknum, bufferinfo->blockinfo.blkno,
|
||||||
|
LSN_CHECK_ERROR);
|
||||||
} else {
|
} else {
|
||||||
ereport(PANIC, (errmsg("lsn check error, lsn in record (%X/%X) ,lsn in current page %X/%X, "
|
ereport(PANIC, (errmsg("lsn check error, lsn in record (%X/%X) ,lsn in current page %X/%X, "
|
||||||
"page info:%u/%u/%u forknum %d blknum:%u lsn %X/%X",
|
"page info:%u/%u/%u forknum %d blknum:%u lsn %X/%X",
|
||||||
|
@ -62,20 +62,28 @@ typedef struct xl_invalid_page_key {
|
|||||||
|
|
||||||
typedef struct xl_invalid_page {
|
typedef struct xl_invalid_page {
|
||||||
xl_invalid_page_key key; /* hash key ... must be first */
|
xl_invalid_page_key key; /* hash key ... must be first */
|
||||||
bool present; /* page existed but contained zeroes */
|
InvalidPageType type; /* invalid page type */
|
||||||
} xl_invalid_page;
|
} xl_invalid_page;
|
||||||
|
|
||||||
/* Report a reference to an invalid page */
|
/* Report a reference to an invalid page */
|
||||||
static void report_invalid_page(int elevel, const RelFileNode &node, ForkNumber forkno, BlockNumber blkno, bool present)
|
static void report_invalid_page(int elevel, const RelFileNode &node, ForkNumber forkno, BlockNumber blkno, InvalidPageType type)
|
||||||
{
|
{
|
||||||
char *path = relpathperm(node, forkno);
|
char *path = relpathperm(node, forkno);
|
||||||
|
|
||||||
if (present)
|
if (type == NOT_INITIALIZED) {
|
||||||
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
errmsg("page %u of relation %s is uninitialized", blkno, path)));
|
errmsg("page %u of relation %s is uninitialized", blkno, path)));
|
||||||
else
|
}
|
||||||
|
else if (type == NOT_PRESENT) {
|
||||||
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
errmsg("page %u of relation %s does not exist", blkno, path)));
|
errmsg("page %u of relation %s does not exist", blkno, path)));
|
||||||
|
} else if (type == LSN_CHECK_ERROR) {
|
||||||
|
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
|
errmsg("page %u of relation %s lsn check error", blkno, path)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ereport(elevel, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
|
errmsg("page %u of relation %s unkown error", blkno, path)));
|
||||||
pfree(path);
|
pfree(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +111,7 @@ void closeXLogRead()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Log a reference to an invalid page */
|
/* Log a reference to an invalid page */
|
||||||
void log_invalid_page(const RelFileNode &node, ForkNumber forkno, BlockNumber blkno, bool present)
|
void log_invalid_page(const RelFileNode &node, ForkNumber forkno, BlockNumber blkno, InvalidPageType type)
|
||||||
{
|
{
|
||||||
xl_invalid_page_key key;
|
xl_invalid_page_key key;
|
||||||
xl_invalid_page *hentry = NULL;
|
xl_invalid_page *hentry = NULL;
|
||||||
@ -120,7 +128,7 @@ void log_invalid_page(const RelFileNode &node, ForkNumber forkno, BlockNumber bl
|
|||||||
* something about the XLOG record that generated the reference).
|
* something about the XLOG record that generated the reference).
|
||||||
*/
|
*/
|
||||||
if (log_min_messages <= DEBUG1 || client_min_messages <= DEBUG1)
|
if (log_min_messages <= DEBUG1 || client_min_messages <= DEBUG1)
|
||||||
report_invalid_page(LOG, node, forkno, blkno, present);
|
report_invalid_page(LOG, node, forkno, blkno, type);
|
||||||
|
|
||||||
if (t_thrd.xlog_cxt.invalid_page_tab == NULL) {
|
if (t_thrd.xlog_cxt.invalid_page_tab == NULL) {
|
||||||
/* create hash table when first needed */
|
/* create hash table when first needed */
|
||||||
@ -148,7 +156,7 @@ void log_invalid_page(const RelFileNode &node, ForkNumber forkno, BlockNumber bl
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* hash_search already filled in the key */
|
/* hash_search already filled in the key */
|
||||||
hentry->present = present;
|
hentry->type = type;
|
||||||
} else {
|
} else {
|
||||||
/* repeat reference ... leave "present" as it was */
|
/* repeat reference ... leave "present" as it was */
|
||||||
}
|
}
|
||||||
@ -236,7 +244,7 @@ void PrintInvalidPage()
|
|||||||
xl_invalid_page *hentry = NULL;
|
xl_invalid_page *hentry = NULL;
|
||||||
hash_seq_init(&status, t_thrd.xlog_cxt.invalid_page_tab);
|
hash_seq_init(&status, t_thrd.xlog_cxt.invalid_page_tab);
|
||||||
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
||||||
report_invalid_page(LOG, hentry->key.node, hentry->key.forkno, hentry->key.blkno, hentry->present);
|
report_invalid_page(LOG, hentry->key.node, hentry->key.forkno, hentry->key.blkno, hentry->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +298,7 @@ static bool XLogCheckInvalidPages_ForSingle(void)
|
|||||||
* only PANIC after we've dumped all the available info.
|
* only PANIC after we've dumped all the available info.
|
||||||
*/
|
*/
|
||||||
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
||||||
report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno, hentry->key.blkno, hentry->present);
|
report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno, hentry->key.blkno, hentry->type);
|
||||||
t_thrd.xlog_cxt.invaildPageCnt++;
|
t_thrd.xlog_cxt.invaildPageCnt++;
|
||||||
foundone = true;
|
foundone = true;
|
||||||
}
|
}
|
||||||
@ -351,7 +359,7 @@ void XLogCheckInvalidPages(void)
|
|||||||
*/
|
*/
|
||||||
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
while ((hentry = (xl_invalid_page *)hash_seq_search(&status)) != NULL) {
|
||||||
report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno, hentry->key.blkno,
|
report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno, hentry->key.blkno,
|
||||||
hentry->present);
|
hentry->type);
|
||||||
t_thrd.xlog_cxt.invaildPageCnt++;
|
t_thrd.xlog_cxt.invaildPageCnt++;
|
||||||
foundone = true;
|
foundone = true;
|
||||||
}
|
}
|
||||||
@ -581,7 +589,7 @@ Buffer XLogReadBufferExtendedWithLocalBuffer(RelFileNode rnode, ForkNumber forkn
|
|||||||
buffer = ReadBuffer_common_for_localbuf(rnode, RELPERSISTENCE_PERMANENT, forknum, blkno, mode, NULL, &hit);
|
buffer = ReadBuffer_common_for_localbuf(rnode, RELPERSISTENCE_PERMANENT, forknum, blkno, mode, NULL, &hit);
|
||||||
} else {
|
} else {
|
||||||
if (mode == RBM_NORMAL) {
|
if (mode == RBM_NORMAL) {
|
||||||
log_invalid_page(rnode, forknum, blkno, false);
|
log_invalid_page(rnode, forknum, blkno, NOT_PRESENT);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
if (mode == RBM_NORMAL_NO_LOG)
|
if (mode == RBM_NORMAL_NO_LOG)
|
||||||
@ -612,7 +620,7 @@ Buffer XLogReadBufferExtendedWithLocalBuffer(RelFileNode rnode, ForkNumber forkn
|
|||||||
if (PageIsNew(page)) {
|
if (PageIsNew(page)) {
|
||||||
Assert(!PageIsLogical(page));
|
Assert(!PageIsLogical(page));
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
log_invalid_page(rnode, forknum, blkno, true);
|
log_invalid_page(rnode, forknum, blkno, NOT_INITIALIZED);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -646,7 +654,7 @@ Buffer XLogReadBufferExtendedWithoutBuffer(RelFileNode rnode, ForkNumber forknum
|
|||||||
buffer = ReadBuffer_common_for_direct(rnode, RELPERSISTENCE_PERMANENT, forknum, blkno, mode);
|
buffer = ReadBuffer_common_for_direct(rnode, RELPERSISTENCE_PERMANENT, forknum, blkno, mode);
|
||||||
} else {
|
} else {
|
||||||
if (mode == RBM_NORMAL) {
|
if (mode == RBM_NORMAL) {
|
||||||
log_invalid_page(rnode, forknum, blkno, false);
|
log_invalid_page(rnode, forknum, blkno, NOT_PRESENT);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
if (mode == RBM_NORMAL_NO_LOG)
|
if (mode == RBM_NORMAL_NO_LOG)
|
||||||
@ -677,7 +685,7 @@ Buffer XLogReadBufferExtendedWithoutBuffer(RelFileNode rnode, ForkNumber forknum
|
|||||||
if (PageIsNew(page)) {
|
if (PageIsNew(page)) {
|
||||||
Assert(!PageIsLogical(page));
|
Assert(!PageIsLogical(page));
|
||||||
XLogRedoBufferReleaseFunc(buffer);
|
XLogRedoBufferReleaseFunc(buffer);
|
||||||
log_invalid_page(rnode, forknum, blkno, true);
|
log_invalid_page(rnode, forknum, blkno, NOT_INITIALIZED);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -741,7 +749,7 @@ Buffer XLogReadBufferExtended(const RelFileNode &rnode, ForkNumber forknum, Bloc
|
|||||||
} else {
|
} else {
|
||||||
/* hm, page doesn't exist in file */
|
/* hm, page doesn't exist in file */
|
||||||
if (mode == RBM_NORMAL) {
|
if (mode == RBM_NORMAL) {
|
||||||
log_invalid_page(rnode, forknum, blkno, false);
|
log_invalid_page(rnode, forknum, blkno, NOT_PRESENT);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
if (mode == RBM_NORMAL_NO_LOG)
|
if (mode == RBM_NORMAL_NO_LOG)
|
||||||
@ -785,7 +793,7 @@ Buffer XLogReadBufferExtended(const RelFileNode &rnode, ForkNumber forknum, Bloc
|
|||||||
if (PageIsNew(page)) {
|
if (PageIsNew(page)) {
|
||||||
Assert(!PageIsLogical(page));
|
Assert(!PageIsLogical(page));
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
log_invalid_page(rnode, forknum, blkno, true);
|
log_invalid_page(rnode, forknum, blkno, NOT_INITIALIZED);
|
||||||
return InvalidBuffer;
|
return InvalidBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,12 @@ typedef enum {
|
|||||||
* replayed) */
|
* replayed) */
|
||||||
} XLogRedoAction;
|
} XLogRedoAction;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NOT_PRESENT,
|
||||||
|
NOT_INITIALIZED,
|
||||||
|
LSN_CHECK_ERROR,
|
||||||
|
}InvalidPageType;
|
||||||
|
|
||||||
extern bool XLogHaveInvalidPages(void);
|
extern bool XLogHaveInvalidPages(void);
|
||||||
extern void* XLogGetInvalidPages();
|
extern void* XLogGetInvalidPages();
|
||||||
|
|
||||||
@ -44,7 +50,7 @@ extern XLogRedoAction XLogReadBufferForRedo(XLogReaderState* record, uint8 buffe
|
|||||||
extern Relation CreateFakeRelcacheEntry(const RelFileNode& rnode);
|
extern Relation CreateFakeRelcacheEntry(const RelFileNode& rnode);
|
||||||
extern Relation CreateCUReplicationRelation(const RelFileNode& rnode, int BackendId, char relpersistence, const char* relname);
|
extern Relation CreateCUReplicationRelation(const RelFileNode& rnode, int BackendId, char relpersistence, const char* relname);
|
||||||
extern void FreeFakeRelcacheEntry(Relation fakerel);
|
extern void FreeFakeRelcacheEntry(Relation fakerel);
|
||||||
extern void log_invalid_page(const RelFileNode& node, ForkNumber forkno, BlockNumber blkno, bool present);
|
extern void log_invalid_page(const RelFileNode& node, ForkNumber forkno, BlockNumber blkno, InvalidPageType type);
|
||||||
extern int read_local_xlog_page(XLogReaderState* state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr,
|
extern int read_local_xlog_page(XLogReaderState* state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr,
|
||||||
char* cur_page, TimeLineID* pageTLI);
|
char* cur_page, TimeLineID* pageTLI);
|
||||||
extern void closeXLogRead();
|
extern void closeXLogRead();
|
||||||
|
@ -253,6 +253,8 @@ typedef HeapPageHeaderData* HeapPageHeader;
|
|||||||
*/
|
*/
|
||||||
#define PageIsNew(page) (((PageHeader)(page))->pd_upper == 0)
|
#define PageIsNew(page) (((PageHeader)(page))->pd_upper == 0)
|
||||||
|
|
||||||
|
#define PageUpperIsInitNew(page) (((PageHeader)(page))->pd_upper == ((PageHeader)(page))->pd_special)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PageGetItemId
|
* PageGetItemId
|
||||||
* Returns an item identifier of a page.
|
* Returns an item identifier of a page.
|
||||||
|
Reference in New Issue
Block a user