diff --git a/README.md b/README.md
index 5930c1230..aae18697e 100644
--- a/README.md
+++ b/README.md
@@ -45,15 +45,18 @@ for full provenance and the per-version index.
## What's new on the living fork
-- **Serializable Snapshot Isolation (SSI)** — an opt-in `DB_TXN_SNAPSHOT_SAFE`
- transaction mode that detects dangerous read/write dependency structures and
+- **Serializable Snapshot Isolation (SSI)** — the `DB_TXN_SNAPSHOT`
+ transaction mode is now serializable: it detects dangerous read/write
+ dependency structures and
aborts the pivot with `DB_SNAPSHOT_CONFLICT`. Both of Cahill's rw-conflict
detection mechanisms are implemented: the lock-table path (a concurrent
writer meeting a reader's SIREAD marker) and the MVCC version-chain path in
`mp_fget` (a reader handed an older version than one a concurrent writer
committed). SIREAD markers are reclaimed incrementally and bounded (not only
at checkpoint); the commit-time pivot check is race-free against concurrent
- edge recording; and `DB_TXN_SNAPSHOT_SAFE` is rejected with `prepare()`/2PC.
+ edge recording; and a `DB_TXN_SNAPSHOT` transaction is rejected with `prepare()`/2PC.
+ (This fork makes `DB_TXN_SNAPSHOT` serializable and removed the earlier
+ separate `DB_TXN_SNAPSHOT_SAFE` flag — a deliberate ABI break.)
The SIREAD marker/locker/detail lifetime is hardened for concurrent writers:
a family of pre-existing use-after-free bugs (most importantly a lock object
reclaimed while it still held SIREAD markers) was found with TSan/ASan and
diff --git a/build_windows/db.h b/build_windows/db.h
index ddf07507f..0e05f0a16 100644
--- a/build_windows/db.h
+++ b/build_windows/db.h
@@ -985,7 +985,7 @@ struct __db_txn {
#define TXN_READ_COMMITTED 0x01000 /* Txn has degree 2 isolation. */
#define TXN_READ_UNCOMMITTED 0x02000 /* Txn has degree 1 isolation. */
#define TXN_RESTORED 0x04000 /* Txn has been restored. */
-#define TXN_SNAPSHOT 0x08000 /* Snapshot Isolation. */
+#define TXN_SNAPSHOT 0x08000 /* Snapshot isolation substrate (always with SSI). */
#define TXN_SYNC 0x10000 /* Write and sync on prepare/commit. */
#define TXN_WRITE_NOSYNC 0x20000 /* Write only on prepare/commit. */
#define TXN_BULK 0x40000 /* Enable bulk loading optimization. */
@@ -3050,7 +3050,6 @@ typedef struct entry {
#define DB_TXN_NOT_DURABLE 0x00000004
#define DB_TXN_NOWAIT 0x00000002
#define DB_TXN_SNAPSHOT 0x00000004
-#define DB_TXN_SNAPSHOT_SAFE 0x00000800
#define DB_TXN_SYNC 0x00000008
#define DB_TXN_WAIT 0x00000080
#define DB_TXN_WRITE_NOSYNC 0x00000020
diff --git a/dist/api_flags b/dist/api_flags
index d2c8bbfb7..9febf8f5c 100644
--- a/dist/api_flags
+++ b/dist/api_flags
@@ -275,8 +275,7 @@ DbEnv.txn_begin
DB_TXN_NOWAIT # Do not wait for locks
DB_TXN_FAMILY # Cursors and child txns are
# independent but lock-compatible
- DB_TXN_SNAPSHOT # Snapshot isolation
- DB_TXN_SNAPSHOT_SAFE __PIN=0x00000800 # Serializable snapshot isolation (SSI)
+ DB_TXN_SNAPSHOT # Serializable snapshot isolation (SSI)
DB_TXN_SYNC # Always sync log on commit
DB_TXN_WAIT # Always wait for locks in this txn
DB_TXN_WRITE_NOSYNC # Write the log but don't sync
diff --git a/docs_src/_migrate/flag-reconcile.md b/docs_src/_migrate/flag-reconcile.md
index ae444b02e..79d771c7c 100644
--- a/docs_src/_migrate/flag-reconcile.md
+++ b/docs_src/_migrate/flag-reconcile.md
@@ -24,8 +24,8 @@ environment / database flag surfaces the SSI work touched. Sources of truth:
| DB_TXN_FAMILY | **MISSING** | **added** (txnbegin.md) |
| DB_TXN_NOSYNC | doc | doc |
| DB_TXN_NOWAIT | doc | doc |
-| DB_TXN_SNAPSHOT | doc | doc |
-| DB_TXN_SNAPSHOT_SAFE | **MISSING** | **added** (txnbegin.md, +guides, +return codes) |
+| DB_TXN_SNAPSHOT | doc | doc (now = SSI) |
+| DB_TXN_SNAPSHOT_SAFE | *removed* | flag removed — folded into DB_TXN_SNAPSHOT |
| DB_TXN_SYNC | doc | doc |
| DB_TXN_WAIT | doc | doc |
| DB_TXN_WRITE_NOSYNC | doc | doc |
@@ -58,10 +58,11 @@ Every `txn_begin` flag the engine accepts is now documented.
| DB_YIELDCPU | doc |
| DB_HOTBACKUP_IN_PROGRESS | doc |
-Note: `DB_TXN_SNAPSHOT_SAFE` is deliberately **not** a valid `set_flags`
-flag — SSI is a per-transaction property only (the env `OK_FLAGS` mask accepts
-plain `DB_TXN_SNAPSHOT` but not `_SAFE`). `envset_flags.md` now states this
-explicitly under `DB_TXN_SNAPSHOT`.
+Note: `DB_TXN_SNAPSHOT` is now serializable snapshot isolation (SSI); the
+separate `DB_TXN_SNAPSHOT_SAFE` flag was **removed** and its behavior folded
+into `DB_TXN_SNAPSHOT`, which is a valid `set_flags` env flag (SSI can be set
+environment-wide or per-transaction). `envset_flags.md` states this under
+`DB_TXN_SNAPSHOT`.
## Public return codes (src/dbinc/db.in) — SSI-era
@@ -75,9 +76,10 @@ return *code* an SSI transaction may get, not a `txn_begin` option.
## What this change fixed
-- `DB_TXN_SNAPSHOT_SAFE` (0x800) — the SSI flag our engine work added:
- documented on `api/c/txnbegin.md`, cross-noted on `api/c/envset_flags.md`
- (per-transaction only), and explained in the transactions guide
+- `DB_TXN_SNAPSHOT` — now serializable snapshot isolation (SSI); the earlier
+ separate `DB_TXN_SNAPSHOT_SAFE` (0x800) flag was removed and folded in:
+ documented on `api/c/txnbegin.md`, cross-noted on `api/c/envset_flags.md`,
+ and explained in the transactions guide
(`guides/gsg_txn/isolation.md`) and the programmer's reference
(`guides/programmer_reference/transapp_read.md`).
- `DB_SNAPSHOT_UNSAFE` / `DB_SNAPSHOT_CONFLICT` return codes documented in
diff --git a/docs_src/api/c/envset_flags.md b/docs_src/api/c/envset_flags.md
index 90c71695b..9f72b0779 100644
--- a/docs_src/api/c/envset_flags.md
+++ b/docs_src/api/c/envset_flags.md
@@ -162,7 +162,7 @@ The **flags** parameter must be set by bitwise inclusively **OR**'ing together o
The DB_TXN_SNAPSHOT flag may be used to configure Berkeley DB at any time during the life of the application.
- Note that only plain snapshot isolation can be configured environment-wide. The serializable-snapshot-isolation flag DB_TXN_SNAPSHOT_SAFE is a per-transaction flag only: it is accepted by DB_ENV->txn_begin() but not by `DB_ENV->set_flags()`, so SSI must be requested for each transaction individually.
+ Note that snapshot transactions configured environment-wide with this flag receive serializable snapshot isolation (SSI); `DB_TXN_SNAPSHOT` is now the SSI mode (there is no separate plain-SI flag). The same behavior can be requested per-transaction via DB_ENV->txn_begin().
- `DB_TXN_WRITE_NOSYNC`
diff --git a/docs_src/api/c/txnbegin.md b/docs_src/api/c/txnbegin.md
index 1fc7d21b5..a6fc161f6 100644
--- a/docs_src/api/c/txnbegin.md
+++ b/docs_src/api/c/txnbegin.md
@@ -75,17 +75,13 @@ The **flags** parameter must be set to 0 or by bitwise inclusively **OR**'ing to
- `DB_TXN_SNAPSHOT`
- This transaction will execute with snapshot isolation. For databases with the DB_MULTIVERSION flag set, data values will be read as they are when the transaction begins, without taking read locks. Silently ignored for operations on databases with DB_MULTIVERSION not set on the underlying database (read locks are acquired).
+ This transaction will execute with **serializable snapshot isolation** (SSI): snapshot isolation plus serializable conflict detection (the Cahill SSI algorithm). For databases with the DB_MULTIVERSION flag set, data values are read as they are when the transaction begins, without taking read locks; for databases without DB_MULTIVERSION, read locks are acquired. On top of that consistent snapshot, Berkeley DB tracks read/write anti-dependencies between concurrent snapshot transactions and, when it detects a dependency structure that could produce a non-serializable schedule, aborts one of the transactions so the committed history is equivalent to some serial order.
- The error `DB_LOCK_DEADLOCK` will be returned from update operations if a snapshot transaction attempts to update data which was modified after the snapshot transaction read it.
+ A transaction that hits such a potential anomaly is aborted with one of two Berkeley DB-specific error returns instead of committing: DB_SNAPSHOT_UNSAFE (a potential serializable-snapshot anomaly was detected via a read/write anti-dependency) or DB_SNAPSHOT_CONFLICT (a conflicting snapshot update was detected). On either return the application must abort the transaction and may retry it. The error `DB_LOCK_DEADLOCK` may also be returned from update operations if a snapshot transaction attempts to update data modified after it read the snapshot.
-- `DB_TXN_SNAPSHOT_SAFE`
+ A `DB_TXN_SNAPSHOT` (SSI) transaction **cannot be prepared for two-phase commit**: DB_TXN->prepare() returns `EINVAL` for such a transaction, because SSI's conflict status is not frozen at prepare time and a later-detected anomaly could not be honored after the transaction had entered the prepared state.
- This transaction will execute with **serializable snapshot isolation** (SSI). This is a Berkeley DB extension beyond `DB_TXN_SNAPSHOT`: it implies `DB_TXN_SNAPSHOT` (the transaction reads a consistent snapshot as of its start, as above) and additionally enables serializable conflict detection (the Cahill SSI algorithm). Berkeley DB tracks read/write anti-dependencies between concurrent snapshot-safe transactions and, when it detects a dependency cycle that could produce a non-serializable schedule, aborts one of the transactions so the committed history is equivalent to some serial order.
-
- A transaction that hits such a potential anomaly is aborted with one of two Berkeley DB-specific error returns instead of committing: DB_SNAPSHOT_UNSAFE (a potential serializable-snapshot anomaly was detected via a read/write anti-dependency) or DB_SNAPSHOT_CONFLICT (a conflicting snapshot update was detected). On either return the application must abort the transaction and may retry it. As with `DB_TXN_SNAPSHOT`, snapshot behavior applies to databases opened with DB_MULTIVERSION.
-
- A `DB_TXN_SNAPSHOT_SAFE` (SSI) transaction **cannot be prepared for two-phase commit**: DB_TXN->prepare() returns `EINVAL` for such a transaction, because SSI's conflict status is not frozen at prepare time and a later-detected anomaly could not be honored after the transaction had entered the prepared state.
+ > **Note:** In this fork, `DB_TXN_SNAPSHOT` provides *serializable* snapshot isolation. In stock Oracle Berkeley DB, `DB_TXN_SNAPSHOT` provided only plain (non-serializable) snapshot isolation, and the earlier `DB_TXN_SNAPSHOT_SAFE` flag has been removed — there is no separate non-serializable snapshot mode.
- `DB_TXN_SYNC`
diff --git a/docs_src/guides/gsg_txn/isolation.md b/docs_src/guides/gsg_txn/isolation.md
index 123816139..ce289a5c8 100644
--- a/docs_src/guides/gsg_txn/isolation.md
+++ b/docs_src/guides/gsg_txn/isolation.md
@@ -396,9 +396,9 @@ main(void)
#### Serializable Snapshot Isolation
-Berkeley DB also offers *serializable snapshot isolation* (SSI), a stronger mode selected with the `DB_TXN_SNAPSHOT_SAFE` flag. Plain snapshot isolation (`DB_TXN_SNAPSHOT`, above) gives each transaction a consistent view as of its start and avoids read locks, but it permits a small class of anomalies (write skew) that a fully serializable schedule would not. SSI closes that gap: it runs the transaction under snapshot isolation *and* tracks read/write anti-dependencies between concurrent snapshot-safe transactions, aborting a transaction whenever it detects a dependency cycle that could produce a non-serializable outcome.
+In this fork, the `DB_TXN_SNAPSHOT` flag provides *serializable snapshot isolation* (SSI). Plain (non-serializable) snapshot isolation gives each transaction a consistent view as of its start and avoids read locks, but it permits a small class of anomalies (write skew) that a fully serializable schedule would not. SSI closes that gap: it runs the transaction under snapshot isolation *and* tracks read/write anti-dependencies between concurrent snapshot transactions, aborting a transaction whenever it detects a dependency structure that could produce a non-serializable outcome. (Stock Oracle Berkeley DB gave `DB_TXN_SNAPSHOT` only plain SI, with a separate `DB_TXN_SNAPSHOT_SAFE` flag for SSI; that flag has been removed and `DB_TXN_SNAPSHOT` is now always SSI.)
-`DB_TXN_SNAPSHOT_SAFE` is a per-transaction flag; it implies `DB_TXN_SNAPSHOT` and is passed to DB_ENV->txn_begin() the same way. Unlike `DB_TXN_SNAPSHOT`, it cannot be enabled environment-wide through `DB_ENV->set_flags()` — each transaction that wants serializable snapshot isolation must request it.
+`DB_TXN_SNAPSHOT` (SSI) is passed to DB_ENV->txn_begin(), or enabled environment-wide through `DB_ENV->set_flags()`.
Because SSI aborts transactions to preserve serializability, a serializable-snapshot transaction may fail to commit with one of two Berkeley DB-specific return codes:
@@ -407,4 +407,4 @@ Because SSI aborts transactions to preserve serializability, a serializable-snap
In both cases the application must abort the transaction and may retry it, exactly as it would for `DB_LOCK_DEADLOCK`. See Error Returns to Applications for the return-code descriptions.
-One restriction applies: a `DB_TXN_SNAPSHOT_SAFE` transaction cannot be prepared for two-phase commit. DB_TXN->prepare() returns `EINVAL` for such a transaction, because SSI's conflict status is not frozen at prepare time and a later-detected anomaly could not be honored once the transaction had entered the prepared state.
+One restriction applies: a `DB_TXN_SNAPSHOT` (SSI) transaction cannot be prepared for two-phase commit. DB_TXN->prepare() returns `EINVAL` for such a transaction, because SSI's conflict status is not frozen at prepare time and a later-detected anomaly could not be honored once the transaction had entered the prepared state.
diff --git a/docs_src/guides/programmer_reference/program_errorret.md b/docs_src/guides/programmer_reference/program_errorret.md
index d440d76c5..cd7ab60e0 100644
--- a/docs_src/guides/programmer_reference/program_errorret.md
+++ b/docs_src/guides/programmer_reference/program_errorret.md
@@ -58,8 +58,8 @@ The DB_SECONDARY_BAD error is returned if a secondary index has been corrupted.
**DB_SNAPSHOT_CONFLICT**
-The DB_SNAPSHOT_CONFLICT error is returned to a transaction started with the DB_TXN_SNAPSHOT_SAFE flag (serializable snapshot isolation, SSI) when Berkeley DB detects a conflicting snapshot update — an attempt to commit an update that conflicts with another concurrent snapshot-safe transaction. The affected transaction must be aborted; the application may then retry it. This return is specific to serializable snapshot isolation and does not occur for plain DB_TXN_SNAPSHOT transactions.
+The DB_SNAPSHOT_CONFLICT error is returned to a transaction started with the DB_TXN_SNAPSHOT flag (serializable snapshot isolation, SSI) when Berkeley DB detects a conflicting snapshot update — an attempt to commit an update that conflicts with another concurrent snapshot transaction. The affected transaction must be aborted; the application may then retry it. This return is specific to serializable snapshot isolation.
**DB_SNAPSHOT_UNSAFE**
-The DB_SNAPSHOT_UNSAFE error is returned to a transaction started with the DB_TXN_SNAPSHOT_SAFE flag (serializable snapshot isolation, SSI) when Berkeley DB detects a potential serializability anomaly through a read/write anti-dependency: the transaction sits as the pivot of a dangerous structure (it is both the read end and the write end of anti-dependency edges among committed and running transactions) that could otherwise produce a non-serializable schedule. The affected transaction is aborted rather than allowed to commit; the application may then retry it. As with DB_SNAPSHOT_CONFLICT, this return is specific to serializable snapshot isolation.
+The DB_SNAPSHOT_UNSAFE error is returned to a transaction started with the DB_TXN_SNAPSHOT flag (serializable snapshot isolation, SSI) when Berkeley DB detects a potential serializability anomaly through a read/write anti-dependency: the transaction sits as the pivot of a dangerous structure (it is both the read end and the write end of anti-dependency edges among committed and running transactions) that could otherwise produce a non-serializable schedule. The affected transaction is aborted rather than allowed to commit; the application may then retry it. As with DB_SNAPSHOT_CONFLICT, this return is specific to serializable snapshot isolation.
diff --git a/docs_src/guides/programmer_reference/transapp_read.md b/docs_src/guides/programmer_reference/transapp_read.md
index 9667187c3..a82fe9826 100644
--- a/docs_src/guides/programmer_reference/transapp_read.md
+++ b/docs_src/guides/programmer_reference/transapp_read.md
@@ -39,8 +39,8 @@ If the application has update transactions which read many items and only update
### Serializable Snapshot Isolation
-Snapshot isolation as configured with DB_TXN_SNAPSHOT gives each transaction a consistent view as of its start and avoids read locks, but it is not fully serializable: it admits a class of anomalies (write skew) in which two transactions each read data the other then updates. Berkeley DB adds *serializable snapshot isolation* (SSI), selected with the DB_TXN_SNAPSHOT_SAFE flag, which runs the transaction under snapshot isolation and additionally detects the read/write anti-dependency cycles that cause those anomalies, aborting a transaction rather than allowing a non-serializable schedule to commit. SSI implements the Cahill serializable-snapshot-isolation algorithm.
+In this fork, snapshot isolation as configured with DB_TXN_SNAPSHOT is *serializable snapshot isolation* (SSI). Plain (non-serializable) snapshot isolation gives each transaction a consistent view as of its start and avoids read locks, but it is not fully serializable: it admits a class of anomalies (write skew) in which two transactions each read data the other then updates. SSI runs the transaction under snapshot isolation and additionally detects the read/write anti-dependency cycles that cause those anomalies, aborting a transaction rather than allowing a non-serializable schedule to commit. SSI implements the Cahill serializable-snapshot-isolation algorithm. (Stock Oracle Berkeley DB gave `DB_TXN_SNAPSHOT` only plain SI and offered SSI through a separate `DB_TXN_SNAPSHOT_SAFE` flag; that flag has been removed — `DB_TXN_SNAPSHOT` is now always SSI.)
-`DB_TXN_SNAPSHOT_SAFE` implies `DB_TXN_SNAPSHOT` and is likewise passed to DB_ENV->txn_begin(); the same `DB_MULTIVERSION` database configuration applies. It is a per-transaction flag only and cannot be enabled environment-wide with DB_ENV->set_flags().
+`DB_TXN_SNAPSHOT` is passed to DB_ENV->txn_begin() (or set environment-wide with DB_ENV->set_flags()); the `DB_MULTIVERSION` database configuration applies.
-A serializable-snapshot transaction that would violate serializability is aborted before commit and returns one of two Berkeley DB-specific codes: DB_SNAPSHOT_UNSAFE (a potential anomaly detected through a read/write anti-dependency) or DB_SNAPSHOT_CONFLICT (a conflicting snapshot update). The application handles these exactly as it handles DB_LOCK_DEADLOCK: abort the transaction and, if appropriate, retry it. Finally, a `DB_TXN_SNAPSHOT_SAFE` transaction cannot be prepared for two-phase commit — DB_TXN->prepare() returns `EINVAL` because SSI's conflict status is not frozen at prepare time.
+A serializable-snapshot transaction that would violate serializability is aborted before commit and returns one of two Berkeley DB-specific codes: DB_SNAPSHOT_UNSAFE (a potential anomaly detected through a read/write anti-dependency) or DB_SNAPSHOT_CONFLICT (a conflicting snapshot update). The application handles these exactly as it handles DB_LOCK_DEADLOCK: abort the transaction and, if appropriate, retry it. Finally, a `DB_TXN_SNAPSHOT` (SSI) transaction cannot be prepared for two-phase commit — DB_TXN->prepare() returns `EINVAL` because SSI's conflict status is not frozen at prepare time.
diff --git a/lang/tcl/tcl_txn.c b/lang/tcl/tcl_txn.c
index 258a12b72..1071e9cd7 100644
--- a/lang/tcl/tcl_txn.c
+++ b/lang/tcl/tcl_txn.c
@@ -265,7 +265,13 @@ get_timeout: if (i >= objc) {
flag |= DB_TXN_SNAPSHOT;
break;
case TXNSNAPSHOTSAFE:
- flag |= DB_TXN_SNAPSHOT_SAFE;
+ /*
+ * DB_TXN_SNAPSHOT is now serializable snapshot isolation
+ * (SSI); the separate DB_TXN_SNAPSHOT_SAFE flag was
+ * removed. Keep -snapshot_safe as a compatibility alias
+ * for -snapshot so existing SSI tests keep working.
+ */
+ flag |= DB_TXN_SNAPSHOT;
break;
case TXNSYNC:
flag |= DB_TXN_SYNC;
diff --git a/rfc/0003-ssi-serializable-snapshot-isolation.md b/rfc/0003-ssi-serializable-snapshot-isolation.md
index e3a4b6af5..19b50ad56 100644
--- a/rfc/0003-ssi-serializable-snapshot-isolation.md
+++ b/rfc/0003-ssi-serializable-snapshot-isolation.md
@@ -9,9 +9,18 @@
---
+> **Amendment (2026, post-implementation):** the public API was simplified. SSI
+> is no longer a separate `DB_TXN_SNAPSHOT_SAFE` flag — that flag was **removed**
+> and its behavior folded into **`DB_TXN_SNAPSHOT`**, which is now always
+> serializable. There is no separate plain (non-serializable) snapshot-isolation
+> mode in the public API. This is a deliberate ABI break, accepted to avoid the
+> awkward `_SAFE` flag name. Everything below describing `DB_TXN_SNAPSHOT_SAFE`
+> now applies to `DB_TXN_SNAPSHOT`; the internal `TXN_SNAPSHOT_SAFE` state and
+> the SSI machinery are unchanged.
+
## Summary
-An opt-in `DB_TXN_SNAPSHOT_SAFE` transaction mode that provides full
+The `DB_TXN_SNAPSHOT` transaction mode provides full
serializable isolation on top of MVCC snapshot isolation, using Michael
Cahill's Serializable Snapshot Isolation algorithm: detect the dangerous
read/write dependency structures that let snapshot isolation admit
@@ -36,8 +45,9 @@ without a server and without giving up embedded operation.
- Multi-process correctness: SIREAD markers/lockers live in the shared lock
region; the concurrent-writer lifetime is hardened (see the M2/M4 notes) and
guarded by `ssi009` (multi-process stress).
-- On-disk/log/region/ABI: no on-disk or log format change. `DB_TXN_SNAPSHOT_SAFE`
- is a new flag; `prepare()`/2PC rejects it.
+- On-disk/log/region/ABI: no on-disk or log format change. `DB_TXN_SNAPSHOT`
+ is now the SSI mode (the separate `DB_TXN_SNAPSHOT_SAFE` flag was removed — a
+ deliberate ABI break); `prepare()`/2PC rejects an SSI transaction.
## Design
diff --git a/rfc/INDEX.md b/rfc/INDEX.md
index f90604dc3..f3d6328d2 100644
--- a/rfc/INDEX.md
+++ b/rfc/INDEX.md
@@ -7,6 +7,6 @@ process. Status: Draft · Accepted · Rejected · Superseded · Implemented.
|---|-------|--------|------|
| [0001](0001-adaptive-lsm.md) | Adaptive LSM access method (HanoiDB + segment-policy, Bitcask, index-in-WAL) | Draft | Prospective |
| [0002](0002-buffer-swip-aio.md) | Scalable buffer access: tagged swip, optimistic descent, async I/O | Draft | Prospective |
-| [0003](0003-ssi-serializable-snapshot-isolation.md) | Serializable Snapshot Isolation (SSI): `DB_TXN_SNAPSHOT_SAFE`, rw-antidependency detection | Implemented | Normative |
+| [0003](0003-ssi-serializable-snapshot-isolation.md) | Serializable Snapshot Isolation (SSI): `DB_TXN_SNAPSHOT` is serializable, rw-antidependency detection | Implemented | Normative |
diff --git a/src/dbinc/db.in b/src/dbinc/db.in
index e7a00974f..84c58d625 100644
--- a/src/dbinc/db.in
+++ b/src/dbinc/db.in
@@ -954,7 +954,7 @@ struct __db_txn {
#define TXN_READ_COMMITTED 0x01000 /* Txn has degree 2 isolation. */
#define TXN_READ_UNCOMMITTED 0x02000 /* Txn has degree 1 isolation. */
#define TXN_RESTORED 0x04000 /* Txn has been restored. */
-#define TXN_SNAPSHOT 0x08000 /* Snapshot Isolation. */
+#define TXN_SNAPSHOT 0x08000 /* Snapshot isolation substrate (always with SSI). */
#define TXN_SYNC 0x10000 /* Write and sync on prepare/commit. */
#define TXN_WRITE_NOSYNC 0x20000 /* Write only on prepare/commit. */
#define TXN_BULK 0x40000 /* Enable bulk loading optimization. */
diff --git a/src/dbinc_auto/api_flags.in b/src/dbinc_auto/api_flags.in
index 4546fe0d1..9fd49b03b 100644
--- a/src/dbinc_auto/api_flags.in
+++ b/src/dbinc_auto/api_flags.in
@@ -196,7 +196,6 @@
#define DB_TXN_NOT_DURABLE 0x00000004
#define DB_TXN_NOWAIT 0x00000002
#define DB_TXN_SNAPSHOT 0x00000004
-#define DB_TXN_SNAPSHOT_SAFE 0x00000800
#define DB_TXN_SYNC 0x00000008
#define DB_TXN_WAIT 0x00000080
#define DB_TXN_WRITE_NOSYNC 0x00000020
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 32879909d..29b29e57a 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -112,7 +112,6 @@ __txn_begin_pp(dbenv, parent, txnpp, flags)
DB_IGNORE_LEASE |DB_READ_COMMITTED | DB_READ_UNCOMMITTED |
DB_TXN_FAMILY | DB_TXN_NOSYNC | DB_TXN_SNAPSHOT | DB_TXN_SYNC |
DB_TXN_WAIT | DB_TXN_WRITE_NOSYNC | DB_TXN_NOWAIT |
- DB_TXN_SNAPSHOT_SAFE |
DB_TXN_BULK)) != 0)
return (ret);
if ((ret = __db_fcchk(env, "txn_begin", flags,
@@ -231,7 +230,7 @@ __txn_begin(env, ip, parent, txnpp, flags)
F_SET(txn, TXN_READ_UNCOMMITTED);
if (LF_ISSET(DB_TXN_FAMILY))
F_SET(txn, TXN_FAMILY | TXN_INFAMILY | TXN_READONLY);
- if (LF_ISSET(DB_TXN_SNAPSHOT | DB_TXN_SNAPSHOT_SAFE) ||
+ if (LF_ISSET(DB_TXN_SNAPSHOT) ||
F_ISSET(dbenv, DB_ENV_TXN_SNAPSHOT) ||
(parent != NULL && F_ISSET(parent, TXN_SNAPSHOT))) {
if (IS_REP_CLIENT(env)) {
@@ -241,8 +240,14 @@ __txn_begin(env, ip, parent, txnpp, flags)
} else
F_SET(txn, TXN_SNAPSHOT);
}
- /* SSI is snapshot isolation plus serializable conflict detection. */
- if (LF_ISSET(DB_TXN_SNAPSHOT_SAFE) ||
+ /*
+ * DB_TXN_SNAPSHOT is serializable snapshot isolation (SSI): snapshot
+ * isolation plus serializable conflict detection. Any snapshot
+ * transaction gets SSI -- there is no separate plain-SI mode. (A
+ * replication client already returned EINVAL above, so we only reach
+ * here for a snapshot txn that is allowed to be SSI.)
+ */
+ if (F_ISSET(txn, TXN_SNAPSHOT) ||
(parent != NULL && F_ISSET(parent, TXN_SNAPSHOT_SAFE))) {
F_SET(txn, TXN_SNAPSHOT_SAFE);
/*
@@ -1378,7 +1383,7 @@ __txn_prepare(txn, gid)
*/
if (F_ISSET(txn, TXN_SNAPSHOT_SAFE)) {
__db_errx(env, DB_STR("4575",
- "DB_TXN->prepare: DB_TXN_SNAPSHOT_SAFE (SSI) transactions "
+ "DB_TXN->prepare: DB_TXN_SNAPSHOT (SSI) transactions "
"cannot be prepared for two-phase commit"));
ret = EINVAL;
goto err;
diff --git a/test/bench/ssi_abort_bench.c b/test/bench/ssi_abort_bench.c
index a463814d9..b9b6949c8 100644
--- a/test/bench/ssi_abort_bench.c
+++ b/test/bench/ssi_abort_bench.c
@@ -1,7 +1,7 @@
/*-
* libdb SSI abort-rate probe.
*
- * Serializable Snapshot Isolation (DB_TXN_SNAPSHOT_SAFE) prevents write-skew
+ * Serializable Snapshot Isolation (DB_TXN_SNAPSHOT) prevents write-skew
* and other snapshot anomalies by aborting the pivot of a dangerous rw-
* dependency structure. The cost is a nonzero abort rate that grows with
* contention, and -- because Berkeley DB tracks conflicts at PAGE granularity,
@@ -60,7 +60,7 @@ one_txn(targ_t *t)
rk = rand_r(&t->seed) % hotkeys;
wk = rand_r(&t->seed) % hotkeys;
- if (env->txn_begin(env, NULL, &txn, DB_TXN_SNAPSHOT_SAFE) != 0) {
+ if (env->txn_begin(env, NULL, &txn, DB_TXN_SNAPSHOT) != 0) {
t->other++;
return;
}