Skip to content

[BUG]: Potential TOCTOU (Time-of-Check to Time-of-Use) Race Condition in Two-Phase DML Execution #83

Description

@tse-wei-chen

Description

The current DML orchestration workflow utilizes a two-phase transaction strategy for data safety:

  1. Phase 1 (Dry-run): Open Transaction A -> Execute DML -> Fetch affected rows -> Rollback -> Await human approval via MCP.
  2. Phase 2 (Execution): Receive approval -> Open Transaction B -> Execute original DML -> Commit.

While this approach elegantly prevents database locking during human verification, it introduces a classic TOCTOU (Time-of-Check to Time-of-Use) race condition / anomaly under concurrent workloads.

How to Reproduce / The Theoretical Failure Mode

  1. T0 (Dry-run): AI generates an UPDATE statement: UPDATE orders SET status = 'Shipped' WHERE id = 100 AND status = 'Pending';. The tool executes this in Transaction A, confirms 1 row affected, and then rolls back.
  2. T1 (Awaiting Approval): The request goes to the human administrator via the MCP Elicitation UI. During this human think-time (e.g., 10–30 seconds), another concurrent system transaction updates orders(id=100) or deletes it entirely.
  3. T2 (Actual Execution): The human clicks "Approve". Transaction B opens and executes the exact same statement.

Actual Behavior / Consequences

Because the underlying snapshot or state of the database mutated between T0 and T2, Phase 2 might result in 0 rows affected (silent no-op), or worse, mutate data based on stale contextual assumptions that the human approved but are no longer valid.

Suggested Solutions

To mitigate this data-drift anomaly, we could consider:

  1. Optimistic Concurrency Control (OCC): During Phase 1 (Dry-run), automatically append or track the Version / Timestamp / RowVersion of the scanned rows, and enforce those criteria in Phase 2.
  2. Post-Execution State Verification: Compare the actual affected row count or state change of Phase 2 against the captured metrics of Phase 1. If a mismatch is detected, abort/rollback Transaction B and flag an automated warning.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions