Skip to main content

MySQL configuration

Transaction behavior

MySqlEventStorage::storeEvents() runs the complete call in one transaction. It can write events for multiple aggregates and enroll outbox entries in the same transaction. If the PDO connection is already inside a transaction, the adapter joins it and leaves the final commit or rollback to the transaction owner.

The optional batchSize controls how many event inserts are grouped into each internal chunk; it does not weaken the transaction boundary of the public storeEvents() call:

$storage = new MySqlEventStorage($pdo, batchSize: 500);

Use InnoDB for the shipped tables. MyISAM does not provide the transaction semantics required by the Core storage contract.

Event table and ordering

The events table has an auto-increment id for global order and a unique (aggregate_id, version) key for stream concurrency. Aggregate reads order by version; global reads and cursor-based pages order by id.

The payload and metadata columns use MySQL JSON. The default entry factory stores the event payload as JSON text in the persistence record before the adapter binds it to the JSON column.

Snapshots and process managers

MySqlSnapshotStorage keeps one current row per aggregate in snapshots. MySqlSnapshotHistoryStorage stores one row per aggregate/version in snapshot_history. Process-manager state is stored in process_manager_states, with an index on timeout for due-timeout polling.

Transactional outbox

Pass a MySqlOutboxStorage to MySqlEventStorage when events should be delivered through an outbox:

use DomainFlow\EventSourcing\Facade\EventSourcingFacade;
use DomainFlow\EventSourcing\Outbox\OutboxRelay;
use DomainFlow\EventSourcingMySQL\Outbox\MySqlOutboxStorage;
use DomainFlow\EventSourcingMySQL\Storage\MySqlEventStorage;

$outbox = new MySqlOutboxStorage($pdo);
$storage = new MySqlEventStorage($pdo, outbox: $outbox);

// Do not also pass an inline dispatcher to this facade.
$facade = new EventSourcingFacade($storage);
$relay = new OutboxRelay($outbox, $dispatcher);

The outbox row is inserted in the event transaction. outbox contains pending entries and outbox_dead contains entries abandoned after too many attempts. Use the Core OutboxRelay for delivery; delivery is at least once.

Custom database fields

An event can expose getDatabaseFields(): array to add adapter fields beside the standard event columns. MySQL validates the field names before placing them in the generated INSERT; names must be valid SQL identifiers beginning with a letter or underscore. The corresponding columns must already exist in the events table.