Author: movead Date: Fri Jun 12 17:20:21 2020 +0800 doc/src/sgml/config.sgml | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- src/backend/access/transam/csn_log.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------- src/backend/access/transam/csn_snapshot.c | 56 ++++++++++++++++++++++++++++++++------------------------ src/backend/access/transam/xlog.c | 10 ++++++++-- src/backend/storage/ipc/procarray.c | 2 +- src/backend/utils/misc/guc.c | 2 +- src/backend/utils/misc/postgresql.conf.sample | 2 ++ src/backend/utils/time/snapmgr.c | 3 ++- src/include/access/csn_log.h | 9 ++++++++- src/test/modules/Makefile | 1 + src/test/modules/csnsnapshot/Makefile | 18 ++++++++++++++++++ src/test/modules/csnsnapshot/csn_snapshot.conf | 1 + src/test/modules/csnsnapshot/expected/csnsnapshot.out | 1 + src/test/modules/csnsnapshot/sql/csnsnapshot.sql | 1 + src/test/modules/csnsnapshot/t/001_base.pl | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/test/modules/csnsnapshot/t/002_standby.pl | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/test/regress/expected/sysviews.out | 2 +- 17 files changed, 410 insertions(+), 75 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 2908821560..a50ad8bfbe 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -9083,8 +9083,56 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' - + + CSN Based Snapshot + + + By default, The snapshots in PostgreSQL uses the + XID (TransactionID) to identify the status of the transaction, the in-progress + transactions, and the future transactions for all its visibility calculations. + + + + PostgreSQL also provides the CSN (commit-sequence-number) + based mechanism to identify the past-transactions and the ones that are yet to + be started/committed. + + + + + enable_csn_snapshot (boolean) + + enable_csn_snapshot configuration parameter + + + + + + Enable/disable the CSN based transaction visibility tracking for the snapshot. + + + + PostgreSQL uses the clock timestamp as a CSN, + so enabling the CSN based snapshots can be useful for implementing the global + snapshots and global transaction visibility. + + + + when enabled PostgreSQL creates + pg_csn directory under PGDATA to keep + the track of CSN and XID mappings. + + + + The default value is off. + + + + + + + Version and Platform Compatibility diff --git a/src/backend/access/transam/csn_log.c b/src/backend/access/transam/csn_log.c index 4577e61fc3..319e89c805 100644 --- a/src/backend/access/transam/csn_log.c +++ b/src/backend/access/transam/csn_log.c @@ -30,9 +30,28 @@ #include "miscadmin.h" #include "pg_trace.h" #include "utils/snapmgr.h" +#include "storage/shmem.h" bool enable_csn_snapshot; +/* + * We use csnSnapshotActive to judge if csn snapshot enabled instead of by + * enable_csn_snapshot, this design is similar to 'track_commit_timestamp'. + * + * Because in process of replication if master change 'enable_csn_snapshot' + * in a database restart, standby should apply wal record for GUC changed, + * then it's difficult to notice all backends about that. So they can get + * the message by 'csnSnapshotActive' which in share buffer. It will not + * acquire a lock, so without performance issue. + * + */ +typedef struct CSNshapshotShared +{ + bool csnSnapshotActive; +} CSNshapshotShared; + +CSNshapshotShared *csnShared = NULL; + /* * Defines for CSNLog page sizes. A page is the same BLCKSZ as is used * everywhere else in Postgres. @@ -94,9 +113,6 @@ CSNLogSetCSN(TransactionId xid, int nsubxids, int i = 0; int offset = 0; - /* Callers of CSNLogSetCSN() must check GUC params */ - Assert(enable_csn_snapshot); - Assert(TransactionIdIsValid(xid)); pageno = TransactionIdToPage(xid); /* get page of parent */ @@ -167,7 +183,7 @@ static void CSNLogSetCSNInSlot(TransactionId xid, XidCSN csn, int slotno) { int entryno = TransactionIdToPgIndex(xid); - XidCSN *ptr; + XidCSN *ptr; Assert(LWLockHeldByMe(CSNLogControlLock)); @@ -192,9 +208,6 @@ CSNLogGetCSNByXid(TransactionId xid) XidCSN *ptr; XidCSN xid_csn; - /* Callers of CSNLogGetCSNByXid() must check GUC params */ - Assert(enable_csn_snapshot); - /* lock is acquired by SimpleLruReadPage_ReadOnly */ slotno = SimpleLruReadPage_ReadOnly(CsnlogCtl, pageno, xid); ptr = (XidCSN *) (CsnlogCtl->shared->page_buffer[slotno] + entryno * sizeof(XLogRecPtr)); @@ -220,9 +233,6 @@ CSNLogShmemBuffers(void) Size CSNLogShmemSize(void) { - if (!enable_csn_snapshot) - return 0; - return SimpleLruShmemSize(CSNLogShmemBuffers(), 0); } @@ -232,37 +242,25 @@ CSNLogShmemSize(void) void CSNLogShmemInit(void) { - if (!enable_csn_snapshot) - return; + bool found; + CsnlogCtl->PagePrecedes = CSNLogPagePrecedes; SimpleLruInit(CsnlogCtl, "CSNLog Ctl", CSNLogShmemBuffers(), 0, CSNLogControlLock, "pg_csn", LWTRANCHE_CSN_LOG_BUFFERS); + + csnShared = ShmemInitStruct("CSNlog shared", + sizeof(CSNshapshotShared), + &found); } /* - * This func must be called ONCE on system install. It creates the initial - * CSNLog segment. The pg_csn directory is assumed to have been - * created by initdb, and CSNLogShmemInit must have been called already. + * See ActivateCSNlog */ void BootStrapCSNLog(void) { - int slotno; - - if (!enable_csn_snapshot) - return; - - LWLockAcquire(CSNLogControlLock, LW_EXCLUSIVE); - - /* Create and zero the first page of the commit log */ - slotno = ZeroCSNLogPage(0, false); - - /* Make sure it's written out */ - SimpleLruWritePage(CsnlogCtl, slotno); - Assert(!CsnlogCtl->shared->page_dirty[slotno]); - - LWLockRelease(CSNLogControlLock); + return; } /* @@ -290,13 +288,94 @@ ZeroTruncateCSNLogPage(int pageno, bool write_xlog) SimpleLruTruncate(CsnlogCtl, pageno); } +void +ActivateCSNlog(void) +{ + int startPage; + TransactionId nextXid = InvalidTransactionId; + + if (csnShared->csnSnapshotActive) + return; + + + nextXid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid); + startPage = TransactionIdToPage(nextXid); + + /* Create the current segment file, if necessary */ + if (!SimpleLruDoesPhysicalPageExist(CsnlogCtl, startPage)) + { + int slotno; + LWLockAcquire(CSNLogControlLock, LW_EXCLUSIVE); + slotno = ZeroCSNLogPage(startPage, false); + SimpleLruWritePage(CsnlogCtl, slotno); + LWLockRelease(CSNLogControlLock); + } + csnShared->csnSnapshotActive = true; +} + +bool +get_csnlog_status(void) +{ + if(!csnShared) + { + /* Should not arrived */ + elog(ERROR, "We do not have csnShared point"); + } + return csnShared->csnSnapshotActive; +} + +void +DeactivateCSNlog(void) +{ + csnShared->csnSnapshotActive = false; + LWLockAcquire(CSNLogControlLock, LW_EXCLUSIVE); + (void) SlruScanDirectory(CsnlogCtl, SlruScanDirCbDeleteAll, NULL); + LWLockRelease(CSNLogControlLock); +} + +void +StartupCSN(void) +{ + ActivateCSNlog(); +} + +void +CompleteCSNInitialization(void) +{ + /* + * If the feature is not enabled, turn it off for good. This also removes + * any leftover data. + * + * Conversely, we activate the module if the feature is enabled. This is + * necessary for primary and standby as the activation depends on the + * control file contents at the beginning of recovery or when a + * XLOG_PARAMETER_CHANGE is replayed. + */ + if (!get_csnlog_status()) + DeactivateCSNlog(); + else + ActivateCSNlog(); +} + +void +CSNlogParameterChange(bool newvalue, bool oldvalue) +{ + if (newvalue) + { + if (!csnShared->csnSnapshotActive) + ActivateCSNlog(); + } + else if (csnShared->csnSnapshotActive) + DeactivateCSNlog(); +} + /* * This must be called ONCE during postmaster or standalone-backend shutdown */ void ShutdownCSNLog(void) { - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; /* @@ -316,7 +395,7 @@ ShutdownCSNLog(void) void CheckPointCSNLog(void) { - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; /* @@ -344,7 +423,7 @@ ExtendCSNLog(TransactionId newestXact) { int pageno; - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; /* @@ -375,9 +454,9 @@ ExtendCSNLog(TransactionId newestXact) void TruncateCSNLog(TransactionId oldestXact) { - int cutoffPage; + int cutoffPage; - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; /* @@ -390,7 +469,6 @@ TruncateCSNLog(TransactionId oldestXact) */ TransactionIdRetreat(oldestXact); cutoffPage = TransactionIdToPage(oldestXact); - ZeroTruncateCSNLogPage(cutoffPage, true); } @@ -443,7 +521,6 @@ WriteXidCsnXlogRec(TransactionId xid, int nsubxids, TransactionId *subxids, XidCSN csn) { xl_xidcsn_set xlrec; - XLogRecPtr recptr; xlrec.xtop = xid; xlrec.nsubxacts = nsubxids; @@ -452,8 +529,7 @@ WriteXidCsnXlogRec(TransactionId xid, int nsubxids, XLogBeginInsert(); XLogRegisterData((char *) &xlrec, MinSizeOfXidCSNSet); XLogRegisterData((char *) subxids, nsubxids * sizeof(TransactionId)); - recptr = XLogInsert(RM_CSNLOG_ID, XLOG_CSN_SETXIDCSN); - XLogFlush(recptr); + XLogInsert(RM_CSNLOG_ID, XLOG_CSN_SETXIDCSN); } /* @@ -473,12 +549,9 @@ WriteZeroCSNPageXlogRec(int pageno) static void WriteTruncateCSNXlogRec(int pageno) { - XLogRecPtr recptr; - return; XLogBeginInsert(); XLogRegisterData((char *) (&pageno), sizeof(int)); - recptr = XLogInsert(RM_CSNLOG_ID, XLOG_CSN_TRUNCATE); - XLogFlush(recptr); + XLogInsert(RM_CSNLOG_ID, XLOG_CSN_TRUNCATE); } diff --git a/src/backend/access/transam/csn_snapshot.c b/src/backend/access/transam/csn_snapshot.c index ec090fd499..d7d0b5e90f 100644 --- a/src/backend/access/transam/csn_snapshot.c +++ b/src/backend/access/transam/csn_snapshot.c @@ -62,10 +62,7 @@ CSNSnapshotShmemSize(void) { Size size = 0; - if (enable_csn_snapshot) - { - size += MAXALIGN(sizeof(CSNSnapshotState)); - } + size += MAXALIGN(sizeof(CSNSnapshotState)); return size; } @@ -76,17 +73,14 @@ CSNSnapshotShmemInit() { bool found; - if (enable_csn_snapshot) + csnState = ShmemInitStruct("csnState", + sizeof(CSNSnapshotState), + &found); + if (!found) { - csnState = ShmemInitStruct("csnState", - sizeof(CSNSnapshotState), - &found); - if (!found) - { - csnState->last_max_csn = 0; - csnState->last_csn_log_wal = 0; - SpinLockInit(&csnState->lock); - } + csnState->last_max_csn = 0; + csnState->last_csn_log_wal = 0; + SpinLockInit(&csnState->lock); } } @@ -104,7 +98,7 @@ GenerateCSN(bool locked) instr_time current_time; SnapshotCSN csn; - Assert(enable_csn_snapshot); + Assert(get_csnlog_status()); /* * TODO: create some macro that add small random shift to current time. @@ -140,7 +134,7 @@ TransactionIdGetXidCSN(TransactionId xid) { XidCSN xid_csn; - Assert(enable_csn_snapshot); + Assert(get_csnlog_status()); /* Handle permanent TransactionId's for which we don't have mapping */ if (!TransactionIdIsNormal(xid)) @@ -222,7 +216,7 @@ XidInvisibleInCSNSnapshot(TransactionId xid, Snapshot snapshot) { XidCSN csn; - Assert(enable_csn_snapshot); + Assert(get_csnlog_status()); csn = TransactionIdGetXidCSN(xid); @@ -277,7 +271,7 @@ void CSNSnapshotAbort(PGPROC *proc, TransactionId xid, int nsubxids, TransactionId *subxids) { - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; CSNLogSetCSN(xid, nsubxids, subxids, AbortedXidCSN, true); @@ -310,7 +304,7 @@ CSNSnapshotPrecommit(PGPROC *proc, TransactionId xid, XidCSN oldassignedXidCsn = InProgressXidCSN; bool in_progress; - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; /* Set InDoubt status if it is local transaction */ @@ -348,7 +342,7 @@ CSNSnapshotCommit(PGPROC *proc, TransactionId xid, { volatile XidCSN assigned_xid_csn; - if (!enable_csn_snapshot) + if (!get_csnlog_status()) return; if (!TransactionIdIsValid(xid)) @@ -391,10 +385,24 @@ get_last_log_wal_csn(void) } /* - * 'xmin_for_csn' for when turn xid-snapshot to csn-snapshot + * */ void -set_xmin_for_csn(void) +prepare_csn_env(bool enable) { - csnState->xmin_for_csn = XidFromFullTransactionId(ShmemVariableCache->nextFullXid); -} + TransactionId nextxid = InvalidTransactionId; + + if(enable) + { + nextxid = XidFromFullTransactionId(ShmemVariableCache->nextFullXid); + /* 'xmin_for_csn' for when turn xid-snapshot to csn-snapshot */ + csnState->xmin_for_csn = nextxid; + /* produce the csnlog segment we want now and seek to current page */ + ActivateCSNlog(); + } + else + { + /* Try to drop all csnlog seg */ + DeactivateCSNlog(); + } +} \ No newline at end of file diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index a6e6c760b1..e69085fdc0 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -79,6 +79,7 @@ #include "utils/relmapper.h" #include "utils/snapmgr.h" #include "utils/timestamp.h" +#include "access/csn_log.h" extern uint32 bootstrap_data_checksum_version; @@ -6802,6 +6803,9 @@ StartupXLOG(void) if (ControlFile->track_commit_timestamp) StartupCommitTs(); + if(ControlFile->enable_csn_snapshot) + StartupCSN(); + /* * Recover knowledge about replay progress of known replication partners. */ @@ -7918,6 +7922,7 @@ StartupXLOG(void) * commit timestamp. */ CompleteCommitTsInitialization(); + CompleteCSNInitialization(); /* * All done with end-of-recovery actions. @@ -9758,8 +9763,7 @@ XLogReportParameters(void) LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); if (enable_csn_snapshot != ControlFile->enable_csn_snapshot) - set_xmin_for_csn(); - + prepare_csn_env(enable_csn_snapshot); ControlFile->MaxConnections = MaxConnections; ControlFile->max_worker_processes = max_worker_processes; ControlFile->max_wal_senders = max_wal_senders; @@ -10201,6 +10205,8 @@ xlog_redo(XLogReaderState *record) CommitTsParameterChange(xlrec.track_commit_timestamp, ControlFile->track_commit_timestamp); ControlFile->track_commit_timestamp = xlrec.track_commit_timestamp; + CSNlogParameterChange(xlrec.enable_csn_snapshot, + ControlFile->enable_csn_snapshot); ControlFile->enable_csn_snapshot = xlrec.enable_csn_snapshot; UpdateControlFile(); diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index f8db77ccd7..e066801933 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -1734,7 +1734,7 @@ GetSnapshotData(Snapshot snapshot) * Take XidCSN under ProcArrayLock so the snapshot stays * synchronized. */ - if (!snapshot->takenDuringRecovery && enable_csn_snapshot) + if (!snapshot->takenDuringRecovery && get_csnlog_status()) xid_csn = GenerateCSN(false); LWLockRelease(ProcArrayLock); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 6634804de6..e458ef6a09 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -1170,7 +1170,7 @@ static struct config_bool ConfigureNamesBool[] = gettext_noop("Used to achieve REPEATEBLE READ isolation level for postgres_fdw transactions.") }, &enable_csn_snapshot, - true, /* XXX: set true to simplify tesing. XXX2: Seems that RESOURCES_MEM isn't the best catagory */ + false, NULL, NULL, NULL }, { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 3a25287a39..092a2743cd 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -296,6 +296,8 @@ # (change requires restart) #track_commit_timestamp = off # collect timestamp of transaction commit # (change requires restart) +#enable_csn_snapshot = off # enable csn base snapshot + # (change requires restart) # - Master Server - diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 218f32e8ec..b50b8cbd30 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -52,6 +52,7 @@ #include "access/transam.h" #include "access/xact.h" #include "access/xlog.h" +#include "access/csn_log.h" #include "catalog/catalog.h" #include "lib/pairingheap.h" #include "miscadmin.h" @@ -2244,7 +2245,7 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) in_snapshot = XidInLocalMVCCSnapshot(xid, snapshot); - if (!enable_csn_snapshot) + if (!get_csnlog_status()) { Assert(XidCSNIsFrozen(snapshot->snapshot_csn)); return in_snapshot; diff --git a/src/include/access/csn_log.h b/src/include/access/csn_log.h index b973e0c2ce..5838028a30 100644 --- a/src/include/access/csn_log.h +++ b/src/include/access/csn_log.h @@ -50,6 +50,13 @@ extern void WriteAssignCSNXlogRec(XidCSN xidcsn); extern void set_last_max_csn(XidCSN xidcsn); extern void set_last_log_wal_csn(XidCSN xidcsn); extern XidCSN get_last_log_wal_csn(void); -extern void set_xmin_for_csn(void); +extern void prepare_csn_env(bool enable_csn_snapshot); +extern void CatchCSNLog(void); +extern void ActivateCSNlog(void); +extern void DeactivateCSNlog(void); +extern void StartupCSN(void); +extern void CompleteCSNInitialization(void); +extern void CSNlogParameterChange(bool newvalue, bool oldvalue); +extern bool get_csnlog_status(void); #endif /* CSNLOG_H */ \ No newline at end of file diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile index 29de73c060..86e114e934 100644 --- a/src/test/modules/Makefile +++ b/src/test/modules/Makefile @@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = \ brin \ commit_ts \ + csnsnapshot \ dummy_index_am \ dummy_seclabel \ snapshot_too_old \ diff --git a/src/test/modules/csnsnapshot/Makefile b/src/test/modules/csnsnapshot/Makefile new file mode 100644 index 0000000000..45c4221cd0 --- /dev/null +++ b/src/test/modules/csnsnapshot/Makefile @@ -0,0 +1,18 @@ +# src/test/modules/csnsnapshot/Makefile + +REGRESS = csnsnapshot +REGRESS_OPTS = --temp-config=$(top_srcdir)/src/test/modules/csnsnapshot/csn_snapshot.conf +NO_INSTALLCHECK = 1 + +TAP_TESTS = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/csnsnapshot +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/src/test/modules/csnsnapshot/csn_snapshot.conf b/src/test/modules/csnsnapshot/csn_snapshot.conf new file mode 100644 index 0000000000..e9d3c35756 --- /dev/null +++ b/src/test/modules/csnsnapshot/csn_snapshot.conf @@ -0,0 +1 @@ +track_commit_timestamp = on diff --git a/src/test/modules/csnsnapshot/expected/csnsnapshot.out b/src/test/modules/csnsnapshot/expected/csnsnapshot.out new file mode 100644 index 0000000000..ac28e417b6 --- /dev/null +++ b/src/test/modules/csnsnapshot/expected/csnsnapshot.out @@ -0,0 +1 @@ +create table t1(i int, j int, k varchar); diff --git a/src/test/modules/csnsnapshot/sql/csnsnapshot.sql b/src/test/modules/csnsnapshot/sql/csnsnapshot.sql new file mode 100644 index 0000000000..91539b8c30 --- /dev/null +++ b/src/test/modules/csnsnapshot/sql/csnsnapshot.sql @@ -0,0 +1 @@ +create table t1(i int, j int, k varchar); \ No newline at end of file diff --git a/src/test/modules/csnsnapshot/t/001_base.pl b/src/test/modules/csnsnapshot/t/001_base.pl new file mode 100644 index 0000000000..1c91f4d9f7 --- /dev/null +++ b/src/test/modules/csnsnapshot/t/001_base.pl @@ -0,0 +1,102 @@ +# Single-node test: value can be set, and is still present after recovery + +use strict; +use warnings; + +use TestLib; +use Test::More tests => 5; +use PostgresNode; + +my $node = get_new_node('csntest'); +$node->init; +$node->append_conf('postgresql.conf', qq{ + enable_csn_snapshot = on + csn_snapshot_defer_time = 10 + max_prepared_transactions = 10 + }); +$node->start; + +my $test_1 = 1; + +# Create a table +$node->safe_psql('postgres', 'create table t1(i int, j int)'); + +# insert test record +$node->safe_psql('postgres', 'insert into t1 values(1,1)'); +# export csn snapshot +my $test_snapshot = $node->safe_psql('postgres', 'select pg_csn_snapshot_export()'); +# insert test record +$node->safe_psql('postgres', 'insert into t1 values(2,1)'); + +my $count1 = $node->safe_psql('postgres', "select count(*) from t1"); +is($count1, '2', 'Get right number in nomal query'); +my $count2 = $node->safe_psql('postgres', " + begin transaction isolation level repeatable read; + select pg_csn_snapshot_import($test_snapshot); + select count(*) from t1; + commit;" + ); + +is($count2, ' +1', 'Get right number in csn import query'); + +#prepare transaction test +$node->safe_psql('postgres', " + begin; + insert into t1 values(3,1); + insert into t1 values(3,2); + prepare transaction 'pt3'; + "); +$node->safe_psql('postgres', " + begin; + insert into t1 values(4,1); + insert into t1 values(4,2); + prepare transaction 'pt4'; + "); +$node->safe_psql('postgres', " + begin; + insert into t1 values(5,1); + insert into t1 values(5,2); + prepare transaction 'pt5'; + "); +$node->safe_psql('postgres', " + begin; + insert into t1 values(6,1); + insert into t1 values(6,2); + prepare transaction 'pt6'; + "); +$node->safe_psql('postgres', "commit prepared 'pt4';"); + +# restart with enable_csn_snapshot off +$node->append_conf('postgresql.conf', "enable_csn_snapshot = off"); +$node->restart; +$node->safe_psql('postgres', " + insert into t1 values(7,1); + insert into t1 values(7,2); + "); +$node->safe_psql('postgres', "commit prepared 'pt3';"); +$count1 = $node->safe_psql('postgres', "select count(*) from t1"); +is($count1, '8', 'Get right number in nomal query'); + + +# restart with enable_csn_snapshot on +$node->append_conf('postgresql.conf', "enable_csn_snapshot = on"); +$node->restart; +$node->safe_psql('postgres', " + insert into t1 values(8,1); + insert into t1 values(8,2); + "); +$node->safe_psql('postgres', "commit prepared 'pt5';"); +$count1 = $node->safe_psql('postgres', "select count(*) from t1"); +is($count1, '12', 'Get right number in nomal query'); + +# restart with enable_csn_snapshot off +$node->append_conf('postgresql.conf', "enable_csn_snapshot = on"); +$node->restart; +$node->safe_psql('postgres', " + insert into t1 values(9,1); + insert into t1 values(9,2); + "); +$node->safe_psql('postgres', "commit prepared 'pt6';"); +$count1 = $node->safe_psql('postgres', "select count(*) from t1"); +is($count1, '16', 'Get right number in nomal query'); diff --git a/src/test/modules/csnsnapshot/t/002_standby.pl b/src/test/modules/csnsnapshot/t/002_standby.pl new file mode 100644 index 0000000000..b7c4ea93b2 --- /dev/null +++ b/src/test/modules/csnsnapshot/t/002_standby.pl @@ -0,0 +1,66 @@ +# Test simple scenario involving a standby + +use strict; +use warnings; + +use TestLib; +use Test::More tests => 6; +use PostgresNode; + +my $bkplabel = 'backup'; +my $master = get_new_node('master'); +$master->init(allows_streaming => 1); + +$master->append_conf( + 'postgresql.conf', qq{ + enable_csn_snapshot = on + max_wal_senders = 5 + }); +$master->start; +$master->backup($bkplabel); + +my $standby = get_new_node('standby'); +$standby->init_from_backup($master, $bkplabel, has_streaming => 1); +$standby->start; + +$master->safe_psql('postgres', "create table t1(i int, j int)"); + +my $guc_on_master = $master->safe_psql('postgres', 'show enable_csn_snapshot'); +is($guc_on_master, 'on', "GUC on master"); + +my $guc_on_standby = $standby->safe_psql('postgres', 'show enable_csn_snapshot'); +is($guc_on_standby, 'on', "GUC on standby"); + +$master->append_conf('postgresql.conf', 'enable_csn_snapshot = off'); +$master->restart; + +$guc_on_master = $master->safe_psql('postgres', 'show enable_csn_snapshot'); +is($guc_on_master, 'off', "GUC off master"); + +$guc_on_standby = $standby->safe_psql('postgres', 'show enable_csn_snapshot'); +is($guc_on_standby, 'on', "GUC on standby"); + +# We consume a large number of transaction,for skip page +for my $i (1 .. 4096) #4096 +{ + $master->safe_psql('postgres', "insert into t1 values(1,$i)"); +} +$master->safe_psql('postgres', "select pg_sleep(2)"); +$master->append_conf('postgresql.conf', 'enable_csn_snapshot = on'); +$master->restart; + +my $count_standby = $standby->safe_psql('postgres', 'select count(*) from t1'); +is($count_standby, '4096', "Ok for siwtch xid-base > csn-base"); #4096 + +# We consume a large number of transaction,for skip page +for my $i (1 .. 4096) #4096 +{ + $master->safe_psql('postgres', "insert into t1 values(1,$i)"); +} +$master->safe_psql('postgres', "select pg_sleep(2)"); + +$master->append_conf('postgresql.conf', 'enable_csn_snapshot = off'); +$master->restart; + +$count_standby = $standby->safe_psql('postgres', 'select count(*) from t1'); +is($count_standby, '8192', "Ok for siwtch csn-base > xid-base"); #8192 \ No newline at end of file diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out index 86a5df0cba..c9118db2b0 100644 --- a/src/test/regress/expected/sysviews.out +++ b/src/test/regress/expected/sysviews.out @@ -73,7 +73,7 @@ select name, setting from pg_settings where name like 'enable%'; name | setting --------------------------------+--------- enable_bitmapscan | on - enable_csn_snapshot | on + enable_csn_snapshot | off enable_gathermerge | on enable_groupingsets_hash_disk | off enable_hashagg | on