Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add documentation for transaction isolation level. #222

Merged
merged 6 commits into from
Dec 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion docs/06-concepts/06-database/08-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all.

Serverpod handles database transactions through the `session.db.transaction` method. The transaction takes a method that performs any database queries or other operations and optionally returns a value.
Serverpod handles database transactions through the `session.db.transaction` method. The method takes a callback function that receives a transaction object.

The transaction is committed when the callback function returns, and rolled back if an exception is thrown. Any return value of the callback function is returned by the `transaction` method.

Simply pass the transaction object to each database operation method to include them in the same atomic operation:

Expand All @@ -18,3 +20,38 @@ var result = await session.db.transaction((transaction) async {
```

In the example we insert a company and an employee in the same transaction. If any of the operations fail, the entire transaction will be rolled back and no changes will be made to the database. If the transaction is successful, the return value will be `true`.

## Transaction isolation

The transaction isolation level can be configured when initiating a transaction. The isolation level determines how the transaction interacts with concurrent database operations. If no isolation level is supplied, the level is determined by the database engine.

:::info

At the time of writing, the default isolation level for the PostgreSQL database engine is `IsolationLevel.readCommitted`.

:::

To set the isolation level, configure the `isolationLevel` property of the `TransactionSettings` object:

```dart
await session.db.transaction(
(transaction) async {
await Company.db.insertRow(session, company, transaction: transaction);
await Employee.db.insertRow(session, employee, transaction: transaction);
},
settings: TransactionSettings(isolationLevel: IsolationLevel.serializable),
);
```

In the example the isolation level is set to `IsolationLevel.serializable`.

The available isolation levels are:

| Isolation Level | Constant | Description |
|-----------------|-----------------------|-------------|
| Read uncommitted | `IsolationLevel.readUncommitted` | Exhibits the same behavior as `IsolationLevel.readCommitted` in PostgresSQL |
| Read committed | `IsolationLevel.readCommitted` | Each statement in the transaction sees a snapshot of the database as of the beginning of that statement. |
| Repeatable read | `IsolationLevel.repeatableRead` | The transaction only observes rows committed before the first statement in the transaction was executed giving a consistent view of the database. If any conflicting writes among concurrent transactions occur, an exception is thrown. |
| Serializable | `IsolationLevel.serializable` | Gives the same guarantees as `IsolationLevel.repeatableRead` but also throws if read rows are updated by other transactions. |

For a detailed explanation of the different isolation levels, see the [PostgreSQL documentation](https://www.postgresql.org/docs/current/transaction-iso.html).
Loading