mongodb protocol_error ai_generated true

MongoServerError: Transaction number 1 on session 0x1234 is not the expected transaction number (expected 2)

ID: mongodb/transaction-number-mismatch

Also available as: JSON · Markdown · 中文
88%Fix Rate
84%Confidence
1Evidence
2024-02-28First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
MongoDB 4.2 active
MongoDB 5.0 active
MongoDB 6.0 active
MongoDB 7.0 active

Root Cause

A client attempted to commit or abort a transaction with a stale transaction number, likely due to a retry logic bug where the same session is reused without incrementing the transaction number, or a session is accidentally shared across concurrent transactions.

generic

中文

客户端尝试使用过时的事务编号提交或中止事务,可能是由于重试逻辑错误,同一会话被重用而未递增事务编号,或会话被意外地在并发事务间共享。

Official Documentation

https://www.mongodb.com/docs/manual/core/transactions/

Workarounds

  1. 90% success Ensure each transaction uses a new session or explicitly increments the transaction number. In Node.js driver: use `session.startTransaction()` and `session.commitTransaction()` within a loop that creates a new session for each attempt. Example: `const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }`
    Ensure each transaction uses a new session or explicitly increments the transaction number. In Node.js driver: use `session.startTransaction()` and `session.commitTransaction()` within a loop that creates a new session for each attempt. Example: `const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }`
  2. 88% success For retry logic, use a fresh session for each retry attempt instead of reusing the same session. In Python: `with client.start_session() as session: session.start_transaction(); ...` inside the retry loop.
    For retry logic, use a fresh session for each retry attempt instead of reusing the same session. In Python: `with client.start_session() as session: session.start_transaction(); ...` inside the retry loop.
  3. 85% success Check for accidental session sharing in async code (e.g., passing the same session object to multiple concurrent coroutines). Use `session.advanceTransactionNumber()` if driver supports it, or enforce sequential transaction processing per session.
    Check for accidental session sharing in async code (e.g., passing the same session object to multiple concurrent coroutines). Use `session.advanceTransactionNumber()` if driver supports it, or enforce sequential transaction processing per session.

中文步骤

  1. 确保每个事务使用新会话或显式递增事务编号。在 Node.js 驱动中:在每次尝试的循环中使用 `session.startTransaction()` 和 `session.commitTransaction()` 创建新会话。示例:`const session = client.startSession(); session.startTransaction(); try { ... await session.commitTransaction(); } catch { await session.abortTransaction(); } finally { session.endSession(); }`
  2. 对于重试逻辑,每次重试尝试使用新会话,而不是重用同一会话。在 Python 中:在重试循环内使用 `with client.start_session() as session: session.start_transaction(); ...`。
  3. 检查异步代码中的意外会话共享(例如,将同一会话对象传递给多个并发协程)。如果驱动程序支持,使用 `session.advanceTransactionNumber()`,或强制每个会话按顺序处理事务。

Dead Ends

Common approaches that don't work:

  1. 90% fail

    The underlying session management bug in the code remains; the error will recur on the next transaction.

  2. 85% fail

    Killing the session only frees server resources; the client code still holds a stale session reference and will create a new session with the same problem.

  3. 95% fail

    The error is about transaction number sequencing, not timeout; changing timeouts has no effect.