Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

Commit 6fb55a5

Browse files
committed
docs: add examples for async transaction context and nested transactions
1 parent f091482 commit 6fb55a5

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

docs/connections_and_transactions.md

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ A transaction can be acquired from the database connection pool:
6767
async with database.transaction():
6868
...
6969
```
70+
7071
It can also be acquired from a specific database connection:
7172

7273
```python
@@ -95,8 +96,54 @@ async def create_users(request):
9596
...
9697
```
9798

98-
Transaction blocks are managed as task-local state. Nested transactions
99-
are fully supported, and are implemented using database savepoints.
99+
Transaction state is stored in the context of the currently executing asynchronous task.
100+
This state is _inherited_ by tasks that are started from within an active transaction:
101+
102+
```python
103+
async def add_excitement(database: Database, id: int):
104+
await database.execute(
105+
"UPDATE notes SET text = CONCAT(text, '!!!') WHERE id = :id",
106+
{"id": id}
107+
)
108+
109+
110+
async with Database(database_url) as database:
111+
async with database.transaction():
112+
# This note won't exist until the transaction closes...
113+
await database.execute(
114+
"INSERT INTO notes(id, text) values (1, 'databases is cool')"
115+
)
116+
# ...but child tasks inherit transaction state!
117+
await asyncio.create_task(add_excitement(database, id=1))
118+
119+
await database.fetch_val("SELECT text FROM notes WHERE id=1")
120+
# ^ returns: "databases is cool!!!"
121+
```
122+
123+
!!! note
124+
In python 3.11, you can opt-out of context propagation by providing a new context to
125+
[`asyncio.create_task`](https://docs.python.org/3.11/library/asyncio-task.html#creating-tasks).
126+
127+
Nested transactions are fully supported, and are implemented using database savepoints:
128+
129+
```python
130+
async with databases.Database(database_url) as db:
131+
async with db.transaction() as outer:
132+
# Do something in the outer transaction
133+
...
134+
135+
# Suppress to prevent influence on the outer transaction
136+
with contextlib.suppress(ValueError):
137+
async with db.transaction():
138+
# Do something in the inner transaction
139+
...
140+
141+
raise ValueError('Abort the inner transaction')
142+
143+
# Observe the results of the outer transaction,
144+
# without effects from the inner transaction.
145+
await db.fetch_all('SELECT * FROM ...')
146+
```
100147

101148
Transaction isolation-level can be specified if the driver backend supports that:
102149

0 commit comments

Comments
 (0)