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