mirror of
https://github.com/postgres/postgres.git
synced 2025-11-29 23:43:17 +03:00
SERIALIZABLE transactions are actually implemented beneath the covers with
transaction snapshots, i.e. a snapshot registered at the beginning of a transaction. Change variable naming and comments to reflect this reality in preparation for a future, truly serializable mode, e.g. Serializable Snapshot Isolation (SSI). For the moment transaction snapshots are still used to implement SERIALIZABLE, but hopefully not for too much longer. Patch by Kevin Grittner and Dan Ports with review and some minor wording changes by me.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.120 2010/07/28 05:22:24 sriggs Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.121 2010/09/11 18:38:56 joe Exp $
|
||||
*
|
||||
* ----------
|
||||
*/
|
||||
@@ -2784,10 +2784,10 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
|
||||
|
||||
/*
|
||||
* Run the plan. For safety we force a current snapshot to be used. (In
|
||||
* serializable mode, this arguably violates serializability, but we
|
||||
* really haven't got much choice.) We don't need to register the
|
||||
* snapshot, because SPI_execute_snapshot will see to it. We need at most
|
||||
* one tuple returned, so pass limit = 1.
|
||||
* transaction-snapshot mode, this arguably violates transaction
|
||||
* isolation rules, but we really haven't got much choice.)
|
||||
* We don't need to register the snapshot, because SPI_execute_snapshot
|
||||
* will see to it. We need at most one tuple returned, so pass limit = 1.
|
||||
*/
|
||||
spi_result = SPI_execute_snapshot(qplan,
|
||||
NULL, NULL,
|
||||
@@ -3332,15 +3332,15 @@ ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan,
|
||||
/*
|
||||
* In READ COMMITTED mode, we just need to use an up-to-date regular
|
||||
* snapshot, and we will see all rows that could be interesting. But in
|
||||
* SERIALIZABLE mode, we can't change the transaction snapshot. If the
|
||||
* caller passes detectNewRows == false then it's okay to do the query
|
||||
* transaction-snapshot mode, we can't change the transaction snapshot.
|
||||
* If the caller passes detectNewRows == false then it's okay to do the query
|
||||
* with the transaction snapshot; otherwise we use a current snapshot, and
|
||||
* tell the executor to error out if it finds any rows under the current
|
||||
* snapshot that wouldn't be visible per the transaction snapshot. Note
|
||||
* that SPI_execute_snapshot will register the snapshots, so we don't need
|
||||
* to bother here.
|
||||
*/
|
||||
if (IsXactIsoLevelSerializable && detectNewRows)
|
||||
if (IsolationUsesXactSnapshot() && detectNewRows)
|
||||
{
|
||||
CommandCounterIncrement(); /* be sure all my own work is visible */
|
||||
test_snapshot = GetLatestSnapshot();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.15 2010/02/26 02:01:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.16 2010/09/11 18:38:56 joe Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -37,10 +37,10 @@
|
||||
|
||||
|
||||
/*
|
||||
* CurrentSnapshot points to the only snapshot taken in a serializable
|
||||
* transaction, and to the latest one taken in a read-committed transaction.
|
||||
* CurrentSnapshot points to the only snapshot taken in transaction-snapshot
|
||||
* mode, and to the latest one taken in a read-committed transaction.
|
||||
* SecondarySnapshot is a snapshot that's always up-to-date as of the current
|
||||
* instant, even on a serializable transaction. It should only be used for
|
||||
* instant, even in transaction-snapshot mode. It should only be used for
|
||||
* special-purpose code (say, RI checking.)
|
||||
*
|
||||
* These SnapshotData structs are static to simplify memory allocation
|
||||
@@ -97,11 +97,11 @@ static int RegisteredSnapshots = 0;
|
||||
bool FirstSnapshotSet = false;
|
||||
|
||||
/*
|
||||
* Remembers whether this transaction registered a serializable snapshot at
|
||||
* Remembers whether this transaction registered a transaction snapshot at
|
||||
* start. We cannot trust FirstSnapshotSet in combination with
|
||||
* IsXactIsoLevelSerializable, because GUC may be reset before us.
|
||||
* IsolationUsesXactSnapshot(), because GUC may be reset before us.
|
||||
*/
|
||||
static bool registered_serializable = false;
|
||||
static bool registered_xact_snapshot = false;
|
||||
|
||||
|
||||
static Snapshot CopySnapshot(Snapshot snapshot);
|
||||
@@ -130,21 +130,21 @@ GetTransactionSnapshot(void)
|
||||
FirstSnapshotSet = true;
|
||||
|
||||
/*
|
||||
* In serializable mode, the first snapshot must live until end of
|
||||
* xact regardless of what the caller does with it, so we must
|
||||
* In transaction-snapshot mode, the first snapshot must live until
|
||||
* end of xact regardless of what the caller does with it, so we must
|
||||
* register it internally here and unregister it at end of xact.
|
||||
*/
|
||||
if (IsXactIsoLevelSerializable)
|
||||
if (IsolationUsesXactSnapshot())
|
||||
{
|
||||
CurrentSnapshot = RegisterSnapshotOnOwner(CurrentSnapshot,
|
||||
TopTransactionResourceOwner);
|
||||
registered_serializable = true;
|
||||
registered_xact_snapshot = true;
|
||||
}
|
||||
|
||||
return CurrentSnapshot;
|
||||
}
|
||||
|
||||
if (IsXactIsoLevelSerializable)
|
||||
if (IsolationUsesXactSnapshot())
|
||||
return CurrentSnapshot;
|
||||
|
||||
CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
|
||||
@@ -155,7 +155,7 @@ GetTransactionSnapshot(void)
|
||||
/*
|
||||
* GetLatestSnapshot
|
||||
* Get a snapshot that is up-to-date as of the current instant,
|
||||
* even if we are executing in SERIALIZABLE mode.
|
||||
* even if we are executing in transaction-snapshot mode.
|
||||
*/
|
||||
Snapshot
|
||||
GetLatestSnapshot(void)
|
||||
@@ -515,13 +515,13 @@ void
|
||||
AtEarlyCommit_Snapshot(void)
|
||||
{
|
||||
/*
|
||||
* On a serializable transaction we must unregister our private refcount
|
||||
* to the serializable snapshot.
|
||||
* In transaction-snapshot mode we must unregister our private refcount
|
||||
* to the transaction-snapshot.
|
||||
*/
|
||||
if (registered_serializable)
|
||||
if (registered_xact_snapshot)
|
||||
UnregisterSnapshotFromOwner(CurrentSnapshot,
|
||||
TopTransactionResourceOwner);
|
||||
registered_serializable = false;
|
||||
registered_xact_snapshot = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -557,5 +557,5 @@ AtEOXact_Snapshot(bool isCommit)
|
||||
SecondarySnapshot = NULL;
|
||||
|
||||
FirstSnapshotSet = false;
|
||||
registered_serializable = false;
|
||||
registered_xact_snapshot = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user