VOOZH about

URL: https://deepwiki.com/stefanak-michal/php-bolt-driver/6.4-transaction-control-messages

⇱ Transaction Control Messages | stefanak-michal/php-bolt-driver | DeepWiki


Loading...
Last indexed: 14 February 2026 (a283bd)
Menu

Transaction Control Messages

Transaction control messages enable explicit transaction management in the Bolt protocol. These messages (BEGIN, COMMIT, ROLLBACK) allow applications to group multiple queries into atomic units of work. Transaction control was introduced in Protocol V3 and is available in all subsequent versions.

Protocol V1 and V2 only support auto-commit transactions, where each RUN message executes in its own implicit transaction. For information on auto-commit vs explicit transactions, see the comparison later in this document.

Overview

The three transaction control messages are implemented as traits in the Bolt\protocol\v3 namespace and composed into protocol versions V3 through V6:

MessageSignatureTraitPurpose
BEGIN0x11Bolt\protocol\v3\BeginMessageInitialize explicit transaction
COMMIT0x12Bolt\protocol\v3\CommitMessagePersist transaction changes
ROLLBACK0x13Bolt\protocol\v3\RollbackMessageDiscard transaction changes

All three traits follow the same pattern: they pack a message signature, write it to the connection via $this->packer->pack() and $this->write(), and add the message to $this->pipelinedMessages array for ordered response processing.

Sources: src/protocol/v3/BeginMessage.php1-23 src/protocol/v3/CommitMessage.php1-36 src/protocol/v3/RollbackMessage.php1-36

Transaction States: TX_READY and TX_STREAMING

When an explicit transaction is active, the server operates in specialized transaction states that mirror the non-transaction states:

Non-Transaction StateTransaction StateTransition
READYTX_READYbegin() received
STREAMINGTX_STREAMINGrun() received within transaction

Transaction State Transitions


The TX_READY state indicates a transaction is open but no queries are currently streaming results. The TX_STREAMING state indicates a transaction is open and at least one query has results waiting to be pulled or discarded.

Sources: src/protocol/v3/BeginMessage.php11-22 src/protocol/v3/CommitMessage.php30-35 src/protocol/v3/RollbackMessage.php29-35

openStreams Counter Management

The AProtocol::$openStreams property tracks the number of active result streams. Both COMMIT and ROLLBACK reset this counter to zero, ensuring proper cleanup of pending results.

Counter Increment (RUN)

When a RUN message succeeds and returns a query identifier (qid), the counter increments:

src/protocol/v3/RunMessage.php35-40


Counter Reset (COMMIT)

The _commit() response handler resets the counter before reading the server response:

src/protocol/v3/CommitMessage.php30-35


Counter Reset (ROLLBACK)

The _rollback() response handler similarly resets the counter:

src/protocol/v3/RollbackMessage.php29-35


openStreams Counter Lifecycle


This reset ensures that any unpulled or undiscarded results are implicitly cleaned up when the transaction ends, preventing resource leaks.

Sources: src/protocol/v3/RunMessage.php35-40 src/protocol/v3/CommitMessage.php30-35 src/protocol/v3/RollbackMessage.php29-35

BEGIN Message

The BEGIN message initiates an explicit transaction. All subsequent RUN messages execute within this transaction context until COMMIT or ROLLBACK is sent.

Message Structure

FieldTypeDescription
SignatureByte0x11
ExtraDictionaryOptional transaction metadata

Implementation

The BeginMessage trait in the Bolt\protocol\v3 namespace implements the message at src/protocol/v3/BeginMessage.php9-22:


The method accepts an $extra array containing optional metadata. The array is cast to (object) for PackStream dictionary serialization. The packed binary data is written via $this->write() (defined in AProtocol), and the message type is appended to $this->pipelinedMessages for response processing.

Extra Parameters

ParameterTypeVersionDescription
bookmarksarrayV3+Transaction bookmarks for causal consistency
tx_timeoutintegerV3+Transaction timeout in milliseconds
tx_metadatadictionaryV3+Application-level metadata
modestringV4+Access mode: "r" (read) or "w" (write)
dbstringV4+Target database name
imp_userstringV4.4+Execute as specified user

Response

The server responds with a SUCCESS message. The response does not include a qid field, so the openStreams counter is not incremented. The connection transitions from READY to TX_READY state.

Sources: src/protocol/v3/BeginMessage.php1-23 README.md117-123

COMMIT Message

The COMMIT message persists all changes made within the current explicit transaction. The server transitions from TX_READY or TX_STREAMING back to READY state.

Message Structure

FieldTypeDescription
SignatureByte0x12

The message has no parameters. All transaction behavior is determined by the BEGIN extra parameters and the queries executed within the transaction.

Implementation

The CommitMessage trait in the Bolt\protocol\v3 namespace implements the message at src/protocol/v3/CommitMessage.php9-23:


The response handler at src/protocol/v3/CommitMessage.php25-35 resets $this->openStreams to zero before reading the server response:


The _commit() method is invoked by AProtocol::getResponse() when processing the response queue.

Response

A successful COMMIT returns a SUCCESS message with optional metadata:

  • bookmark - Transaction bookmark for causal chaining
  • db - Database name (V4+)

If the commit fails, the server returns a FAILURE message. The transaction is implicitly rolled back and the connection enters the FAILED state, requiring a RESET message for recovery.

Sources: src/protocol/v3/CommitMessage.php1-36 README.md138-144

ROLLBACK Message

The ROLLBACK message discards all changes made within the current explicit transaction. The server transitions from TX_READY or TX_STREAMING back to READY state.

Message Structure

FieldTypeDescription
SignatureByte0x13

The message has no parameters.

Implementation

The RollbackMessage trait in the Bolt\protocol\v3 namespace implements the message at src/protocol/v3/RollbackMessage.php9-23:


The response handler at src/protocol/v3/RollbackMessage.php25-35 resets $this->openStreams to zero before reading the server response:


The _rollback() method is invoked by AProtocol::getResponse() when processing the response queue.

Response

A successful ROLLBACK returns a SUCCESS message. Unlike COMMIT, rollback always succeeds even if the transaction is in a failed state, making it safe for error recovery.

Sources: src/protocol/v3/RollbackMessage.php1-36 README.md138-144

Message Pipelining and Response Processing

Transaction messages support pipelining, allowing multiple messages to be sent before reading responses. This optimizes network round-trips by batching operations.

Pipelined Transaction Message Flow


The $this->pipelinedMessages array (property of AProtocol) queues message types in send order. When getResponse() or getResponses() is called, the protocol reads responses in the same order and dispatches to the corresponding response handler method (e.g., _begin(), _commit(), _run()) based on the message type.

Sources: src/protocol/v3/BeginMessage.php20 src/protocol/v3/CommitMessage.php21 src/protocol/v3/RollbackMessage.php21 src/protocol/v3/RunMessage.php26 src/protocol/v3/CommitMessage.php32 src/protocol/v3/RollbackMessage.php31

Transaction Extra Parameters

The BEGIN message accepts various metadata parameters through its $extra array. These parameters control transaction behavior and are protocol-version dependent.

Common Parameters (V3+)

ParameterTypeDescription
bookmarksarrayTransaction bookmarks for causal consistency
tx_timeoutintegerTransaction timeout in milliseconds
tx_metadatadictionaryApplication-level metadata

V4+ Parameters

ParameterTypeDescription
modestringAccess mode: "r" (read) or "w" (write)
dbstringTarget database name

V4.4+ Parameters

ParameterTypeDescription
imp_userstringExecute transaction as specified user

Example Usage


Sources: README.md117-123 src/protocol/v3/BeginMessage.php17-19

Explicit vs Auto-Commit Transactions

The Bolt protocol supports two transaction execution modes. Protocol V1 and V2 only support auto-commit, while V3+ support both modes.

Auto-Commit Mode (All Versions)

When no explicit transaction is active, RUN messages execute in auto-commit mode. Each query is implicitly wrapped in its own transaction that commits immediately after the final result is consumed.

From README.md144:

run executes query in auto-commit transaction if explicit transaction was not open.

Auto-Commit Execution:

  1. Application sends RUN message
  2. Server transitions: READYSTREAMING
  3. Application sends PULL or DISCARD message
  4. Server returns results and commits
  5. Server transitions: STREAMINGREADY

Explicit Transaction Mode (V3+)

When a BEGIN message is sent, all subsequent RUN messages execute within that transaction context. Changes are not persisted until COMMIT is explicitly sent.

Explicit Transaction Execution:

  1. Application sends BEGIN message
  2. Server transitions: READYTX_READY
  3. Application sends one or more RUN + PULL/DISCARD sequences
  4. Server transitions: TX_READYTX_STREAMING for each query
  5. Application sends COMMIT or ROLLBACK
  6. Server transitions: TX_READY/TX_STREAMINGREADY

Transaction Mode Comparison


The key distinction: auto-commit transactions commit after each query, while explicit transactions allow multiple queries to be grouped with atomic commit or rollback.

Sources: README.md138-144 src/protocol/v3/BeginMessage.php11-12 src/protocol/v3/RunMessage.php18-28

Trait Composition Across Protocol Versions

Transaction control messages are implemented as traits in the v3 namespace and composed unchanged into protocol versions V3 through V6. This demonstrates backward compatibility in transaction semantics.

Transaction Trait Files and Composition


The three traits are located at:

Each trait follows the same pattern: pack the signature byte via $this->packer->pack(), write to connection via $this->write(), add to $this->pipelinedMessages array. The response handler methods (prefixed with underscore: _begin(), _commit(), _rollback()) process server responses and manage the $this->openStreams counter.

Sources: src/protocol/v3/BeginMessage.php3 src/protocol/v3/CommitMessage.php3 src/protocol/v3/RollbackMessage.php3

Error Handling

Transaction failures can occur during any phase of the transaction lifecycle. The Bolt protocol provides mechanisms for detecting and recovering from transaction errors.

Transaction Failure Scenarios

ScenarioServer ResponseRecovery Action
Constraint violationFAILUREROLLBACK
Deadlock detectedFAILUREROLLBACK, retry
Query syntax errorFAILUREROLLBACK
Transaction timeoutFAILUREROLLBACK
Network interruptionConnection errorReconnect

Failed State Recovery

When a query within a transaction fails, the server enters the FAILED state. In this state:

  1. No further queries can execute
  2. The transaction must be rolled back
  3. A RESET message must be sent to return to READY state

Error Recovery Sequence


For V1 and V2 protocols without explicit transactions, a RESET message is required after FAILURE:


Sources: README.md277-279 src/protocol/v1/ResetMessage.php12

Usage Examples

Basic Transaction


Transaction with Rollback

The test suite demonstrates transaction rollback in BoltTest::testTransaction() at tests/BoltTest.php111-143:


The test verifies that rolling back a transaction discards all changes, including the created node.

Transaction with Timeout


Transaction with Error Handling


Multi-Database Transaction (V4+)


Transaction with Large Payloads

The test suite demonstrates transactions with large data payloads in BoltTest::testChunking() at tests/BoltTest.php178-203 This verifies that PackStream message chunking works correctly within transactions:


This test validates that the PackStream chunking mechanism (with 0x0000 chunk terminators) functions correctly for large messages within transaction context.

Sources: tests/BoltTest.php178-203 README.md138-144

Protocol Compatibility Matrix

Transaction control messages availability across Bolt protocol versions:

MessageV1V2V3V4V5V6
BEGIN
COMMIT
ROLLBACK

Protocol V1 and V2 do not support explicit transactions. All queries in these versions execute in auto-commit mode. To use transaction control, Protocol V3 or higher must be negotiated.

Sources: README.md138-144 src/protocol/v3/BeginMessage.php13 src/protocol/v3/CommitMessage.php13 src/protocol/v3/RollbackMessage.php13

Refresh this wiki

On this page