Tom Lane <[email protected]> wrote:
> +1 for adding parens; we might want to make a function of it
> someday.
> How about IsolationUsesXactSnapshot
Patch attached.
Joe said that he'll review this weekend and probably commit in a day
or two if there are no objections.
-Kevin
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
***************
*** 2049,2055 **** IndexCheckExclusion(Relation heapRelation,
*
* After completing validate_index(), we wait until all transactions that
* were alive at the time of the reference snapshot are gone; this is
! * necessary to be sure there are none left with a serializable snapshot
* older than the reference (and hence possibly able to see tuples we did
* not index). Then we mark the index "indisvalid" and commit.
Subsequent
* transactions will be able to use it for queries.
--- 2049,2055 ----
*
* After completing validate_index(), we wait until all transactions that
* were alive at the time of the reference snapshot are gone; this is
! * necessary to be sure there are none left with a transaction-based snapshot
* older than the reference (and hence possibly able to see tuples we did
* not index). Then we mark the index "indisvalid" and commit.
Subsequent
* transactions will be able to use it for queries.
*** a/src/backend/commands/trigger.c
--- b/src/backend/commands/trigger.c
***************
*** 2387,2393 **** ltrmark:;
case HeapTupleUpdated:
ReleaseBuffer(buffer);
! if (IsXactIsoLevelSerializable)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not
serialize access due to concurrent update")));
--- 2387,2393 ----
case HeapTupleUpdated:
ReleaseBuffer(buffer);
! if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not
serialize access due to concurrent update")));
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
***************
*** 1554,1560 **** EvalPlanQualFetch(EState *estate, Relation relation, int
lockmode,
case HeapTupleUpdated:
ReleaseBuffer(buffer);
! if (IsXactIsoLevelSerializable)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could
not serialize access due to concurrent update")));
--- 1554,1560 ----
case HeapTupleUpdated:
ReleaseBuffer(buffer);
! if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could
not serialize access due to concurrent update")));
*** a/src/backend/executor/nodeLockRows.c
--- b/src/backend/executor/nodeLockRows.c
***************
*** 130,136 **** lnext:
break;
case HeapTupleUpdated:
! if (IsXactIsoLevelSerializable)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not
serialize access due to concurrent update")));
--- 130,136 ----
break;
case HeapTupleUpdated:
! if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not
serialize access due to concurrent update")));
*** a/src/backend/executor/nodeModifyTable.c
--- b/src/backend/executor/nodeModifyTable.c
***************
*** 328,334 **** ldelete:;
break;
case HeapTupleUpdated:
! if (IsXactIsoLevelSerializable)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize
access due to concurrent update")));
--- 328,334 ----
break;
case HeapTupleUpdated:
! if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize
access due to concurrent update")));
***************
*** 516,522 **** lreplace:;
break;
case HeapTupleUpdated:
! if (IsXactIsoLevelSerializable)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize
access due to concurrent update")));
--- 516,522 ----
break;
case HeapTupleUpdated:
! if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize
access due to concurrent update")));
*** a/src/backend/utils/adt/ri_triggers.c
--- b/src/backend/utils/adt/ri_triggers.c
***************
*** 3332,3346 **** 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
* 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)
{
CommandCounterIncrement(); /* be sure all my own
work is visible */
test_snapshot = GetLatestSnapshot();
--- 3332,3346 ----
/*
* 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
! * xact-snapshot-based modes, 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 (IsolationUsesXactSnapshot() && detectNewRows)
{
CommandCounterIncrement(); /* be sure all my own
work is visible */
test_snapshot = GetLatestSnapshot();
*** a/src/backend/utils/time/snapmgr.c
--- b/src/backend/utils/time/snapmgr.c
***************
*** 37,44 ****
/*
! * CurrentSnapshot points to the only snapshot taken in a serializable
! * transaction, 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
* special-purpose code (say, RI checking.)
--- 37,44 ----
/*
! * CurrentSnapshot points to the only snapshot taken in a xact-snapshot-based
! * transaction; otherwise to the latest one taken.
* 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
* special-purpose code (say, RI checking.)
***************
*** 97,107 **** static int RegisteredSnapshots = 0;
bool FirstSnapshotSet = false;
/*
! * Remembers whether this transaction registered a serializable snapshot at
* start. We cannot trust FirstSnapshotSet in combination with
! * IsXactIsoLevelSerializable, because GUC may be reset before us.
*/
! static bool registered_serializable = false;
static Snapshot CopySnapshot(Snapshot snapshot);
--- 97,107 ----
bool FirstSnapshotSet = false;
/*
! * Remembers whether this transaction registered a transaction-based snapshot
at
* start. We cannot trust FirstSnapshotSet in combination with
! * IsolationUsesXactSnapshot(), because GUC may be reset before us.
*/
! static bool registered_xact_snapshot = false;
static Snapshot CopySnapshot(Snapshot snapshot);
***************
*** 130,150 **** 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
! * register it internally here and unregister it at end of xact.
*/
! if (IsXactIsoLevelSerializable)
{
CurrentSnapshot =
RegisterSnapshotOnOwner(CurrentSnapshot,
TopTransactionResourceOwner);
! registered_serializable = true;
}
return CurrentSnapshot;
}
! if (IsXactIsoLevelSerializable)
return CurrentSnapshot;
CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
--- 130,151 ----
FirstSnapshotSet = true;
/*
! * In xact-snapshot-based isolation levels, 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 (IsolationUsesXactSnapshot())
{
CurrentSnapshot =
RegisterSnapshotOnOwner(CurrentSnapshot,
TopTransactionResourceOwner);
! registered_xact_snapshot = true;
}
return CurrentSnapshot;
}
! if (IsolationUsesXactSnapshot())
return CurrentSnapshot;
CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
***************
*** 155,161 **** GetTransactionSnapshot(void)
/*
* GetLatestSnapshot
* Get a snapshot that is up-to-date as of the current instant,
! * even if we are executing in SERIALIZABLE mode.
*/
Snapshot
GetLatestSnapshot(void)
--- 156,162 ----
/*
* GetLatestSnapshot
* Get a snapshot that is up-to-date as of the current instant,
! * even if we are executing in xact-snapshot-based mode.
*/
Snapshot
GetLatestSnapshot(void)
***************
*** 515,527 **** void
AtEarlyCommit_Snapshot(void)
{
/*
! * On a serializable transaction we must unregister our private refcount
! * to the serializable snapshot.
*/
! if (registered_serializable)
UnregisterSnapshotFromOwner(CurrentSnapshot,
TopTransactionResourceOwner);
! registered_serializable = false;
}
--- 516,528 ----
AtEarlyCommit_Snapshot(void)
{
/*
! * On a xact-snapshot-based transaction we must unregister our private
! * refcount to the xact snapshot.
*/
! if (registered_xact_snapshot)
UnregisterSnapshotFromOwner(CurrentSnapshot,
TopTransactionResourceOwner);
! registered_xact_snapshot = false;
}
***************
*** 557,561 **** AtEOXact_Snapshot(bool isCommit)
SecondarySnapshot = NULL;
FirstSnapshotSet = false;
! registered_serializable = false;
}
--- 558,562 ----
SecondarySnapshot = NULL;
FirstSnapshotSet = false;
! registered_xact_snapshot = false;
}
*** a/src/include/access/xact.h
--- b/src/include/access/xact.h
***************
*** 35,41 **** extern int XactIsoLevel;
* We only implement two isolation levels internally. This macro should
* be used to check which one is selected.
*/
! #define IsXactIsoLevelSerializable (XactIsoLevel >= XACT_REPEATABLE_READ)
/* Xact read-only state */
extern bool DefaultXactReadOnly;
--- 35,41 ----
* We only implement two isolation levels internally. This macro should
* be used to check which one is selected.
*/
! #define IsolationUsesXactSnapshot() (XactIsoLevel >= XACT_REPEATABLE_READ)
/* Xact read-only state */
extern bool DefaultXactReadOnly;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers