<!-- llms-explorer concept facts · https://llms-explorer.com/tree/pinned-secondary-transaction-table-derived-updates-and-coalescing-boundaries/ · pack 2026-11-02 · ~3212 tokens -->

# Pinned secondary transaction-table derived updates and coalescing boundaries

> Source-anchored research for Pinned secondary transaction-table derived updates and coalescing boundaries. Run status: COMPLETED.

Parent: [Retryable Writes](https://llms-explorer.com/tree/retryable-writes/) · 5 facets · 19 facts · page: https://llms-explorer.com/tree/pinned-secondary-transaction-table-derived-updates-and-coalescing-boundaries/

## Structure and components

- The derived transaction-table operation is an update with upsert enabled, targets the session-transactions namespace, and uses the originating operation time and wall-clock time. It has empty operation session information. The constructor is createOplogEntryForTransactionTableUpdate. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)

## How it works

- When coalescing is enabled, the tracker buffers the first eligible entry per session and replaces it for the same transaction number. For a higher transaction number, it emits the previously buffered record and retains the new entry; for a lower number it takes LOGV2_FATAL_NOTRACE with identifier 50843. In the higher-number branch, the code constructs the old derived update, replaces the buffered entry, and then returns the old update for emission. The fatal diagnostic includes the session ID, both transaction numbers and both oplog entries. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
- Selective flush parses the query predicate _id as a logical session identifier, emits and removes only that buffered session, and returns an empty vector when that session is absent. Full flush emits every buffered record and clears the map. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- updateSession classifies transaction entries using entry.isInTransaction(). When a transaction operation generates a table update, the tracker erases any queued retryable-write update for the same session and returns the transaction update immediately. The source explains that retryable writes need the final session record, whereas multi-statement transactions require the timestamps and states of their individual table updates. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h)

## Problems, failure modes and limitations

- In deriveOpsAndFillWriterVectors, operations at or before beginApplyingOpTime are skipped. When a tracker exists, addSessionUpdateOps passes the entry and optional prepared fields to updateSession, stores emitted records in derivedOps, and routes them with addDerivedOps using serial=false. The secondary prepare branch derives inner-operation fields and routes inner operations before invoking this lambda, then continues. The ordinary path invokes the lambda with boost::none before deferring partial transaction operations. In the direct terminal extraction branch, extracted child operations go to addDerivedOps; the source comment states that nested entries cannot have different session updates. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)

## Comparisons and alternatives

- For a preparing kApplyOps entry, the derived state is kPrepared. If its previous-write operation time is null, the record sets its start operation time to the prepare entry’s operation time. Otherwise it returns a delta oplog update containing the new record fields, preserving the existing start operation time instead of overwriting it. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- PreparedTxnDerivedFields contains optional affectedNamespaces and sizeMetadata derived from inner transaction operations, rather than from the outer prepare entry. When supplied for a preparing entry, the tracker canonicalizes supplied namespaces into the transaction record and copies supplied size metadata. The secondary prepare dispatch computes namespaces only when the persistence provider supports preserving prepared transactions in precise checkpoints, and aggregates size metadata only when replicated fast count is enabled. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)

## Facts and statements

- The retryable-write record uses the full session identifier as its record identity and query predicate. It copies transaction number, optional transaction retry counter, last-write operation time and last-write date. For an internal session for a retryable write, it also sets the parent session identifier. createMatchingTransactionTableUpdate serializes the replacement SessionTxnRecord. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- The retryable-write path returns without tracking an entry that lacks a transaction number, asserts that an eligible entry has a session identifier, and excludes partial transaction entries so only a terminal entry advances the session last-write operation time. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- On the retryable-write path, a no-op is ignored unless the migration marker is present and true; it is also ignored if object2 is absent, or empty without being the would-change-owning-shard sentinel. The code identifies this filtering as exclusion of pre/post image no-op entries. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- The disableTransactionUpdateCoalescing constructor option controls immediate emission of one derived record for each eligible retryable-write entry, bypassing the buffer after eligibility filtering. The constructor parameter has a false default; this declaration does not establish deployment feature-flag state. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
- An explicit session-transactions-table entry or a config-database command goes through the flush path. An update uses object2 as the query predicate; a delete uses object. A command flushes the whole buffer. In _flush, inserts, container insert/update/delete operations, no-ops, key-material operations and CMK-rotation operations do not flush pending records. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- The transaction-state builder returns no update for a partial entry whose previous transaction operation time is non-null. The first partial entry sets in-progress state and sets the start operation time to its operation time. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h)
- Transaction-state records copy session identity, conditional parent-session identity, transaction number, retry counter, last-write operation time and date. A transaction-classified no-op maps to committed state. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h)
- For a non-partial transaction entry that reaches the command switch in the transaction-state builder, a non-preparing kApplyOps and a kCommitTransaction command set committed state. A kAbortTransaction command reaching that switch sets aborted state. Partial entries return before the switch: later partial entries return no update, while the first partial entry returns an in-progress record. The builder passes the committed or aborted records to createOplogEntryForTransactionTableUpdate. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
- fillWriterVectors constructs a tracker using disableTransactionUpdateCoalescing, derives operations, then calls flushAll at batch end. If that returns writes, coalescing must be enabled; the caller stores them as derived operations and dispatches them with a null session tracker and null checkpoint validator, so these derived session-table writes are not checkpoint-preprocessed as replicated entries. The flushAll implementation converts each buffered entry through createMatchingTransactionTableUpdate, clears the session map, and returns the derived vector. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.h) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- TxnTableUpdatesGetCoalescedForRetryableWritesWithSameTxnNumber supplies two writes with the same session and transaction number and asserts one derived update with the second write’s lastWriteOpTime. TxnTableUpdatesDoNotGetCoalescedForRetryableWritesAcrossDifferentTxnNumbers supplies transaction numbers 3 and 4 and asserts two derived updates with their respective numbers and timestamps. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- The disabled-coalescing fixture enables featureFlagDisableTransactionUpdateCoalescing with a ServerParameterGuard and asserts two derived records for two writes with the same session and transaction number, retaining each write timestamp. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/session_update_tracker.cpp)
- The mixed-history fixtures cover both directions on one session: retryable write followed by a multi-statement transaction expects the committed transaction record; multi-statement transaction followed by a higher-number retryable write expects the retryable-write record without transaction state. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
