Skip to content

A failed commit leaves the transaction active and locks its entities #409

Description

@StevenBtw

Summary

When a commit fails with a write-write conflict, the transaction stays active in the transaction manager. Every later transaction that writes the same entity then fails with a write-write conflict too, until the process restarts.

Reproduction

import grafeo

db = grafeo.GrafeoDB()
db.execute("INSERT (:Person {name: 'Alix', age: 30})")

ta = db.begin_transaction()
tb = db.begin_transaction()
tb.execute("MATCH (n:Person {name: 'Alix'}) SET n.age = 31")
tb.commit()

ta.execute("MATCH (n:Person {name: 'Alix'}) SET n.age = 32")
try:
    ta.commit()  # fails with a write-write conflict, as expected
except Exception as e:
    print("expected conflict:", e)

tc = db.begin_transaction()
tc.execute("MATCH (n:Person {name: 'Alix'}) SET n.age = 33")  # also fails, and keeps failing until restart

Cause

Session::commit_inner handles the conflict by replaying the property undo log and clearing pending CDC events, but it never calls TransactionManager::abort, does not discard the versions the transaction created and writes no WAL abort record. The only production call to abort is in the rollback path. The transaction stays Active, so:

  • record_write keeps reporting a conflict against it for every later writer of the same entities,
  • active_count stays above zero, which disables the single-writer fast path,
  • min_active_epoch stays pinned, so version garbage collection stops reclaiming newer versions.

Expected

A failed commit aborts the transaction completely: its entities are released, its versions discarded, an abort is logged and the error is returned to the caller.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions