Transactions in Query
@ydbjs/query
provides two helpers: begin
and transaction
.
begin(options?, fn)
— creates a transaction, runsfn(tx, signal)
, commits on success and rolls back on error.transaction(options?, fn)
— alias tobegin
.
Options:
isolation?: 'serializableReadWrite' | 'snapshotReadOnly'
— isolation level (defaultserializableReadWrite
).idempotent?: boolean
— enables retries for conditionally retryable errors. Ensure business logic is idempotent.
signal: AbortSignal
allows canceling long operations inside the callback.
Basic usage
ts
const result = await sql.begin(async (tx) => {
await tx`UPDATE users SET active = false WHERE ...`
return await tx`SELECT * FROM users WHERE active = false`
})
Isolation and idempotency options
ts
await sql.begin({ isolation: 'snapshotReadOnly', idempotent: true }, async (tx) => {
return await tx`SELECT COUNT(*) FROM users`
})
Topic integration (without using)
When inside sql.transaction(...)
, use tx‑aware Topic clients without using
/manual disposal:
ts
import { createTopicTxReader } from '@ydbjs/topic/reader'
import { createTopicTxWriter } from '@ydbjs/topic/writer'
await sql.transaction(async (tx, signal) => {
const reader = createTopicTxReader(tx, driver, { topic: '/Root/my-topic', consumer: 'svc-a' })
for await (const batch of reader.read({ signal })) {
// processing
}
const writer = createTopicTxWriter(tx, driver, { topic: '/Root/my-topic', producer: 'p1' })
writer.write(new TextEncoder().encode('message'))
})
Reader registers updateOffsetsInTransaction
on tx.onCommit
; Writer triggers flush
on tx.onCommit
. Manual disposal inside a transaction is not required.
Timeouts and retries
- Set timeouts per query or per handler.
- See “Advanced → Retries and Idempotency”.
Best practices
- Keep transactions short to reduce blocking/conflicts.
- Prefer
snapshotReadOnly
for read‑only operations when possible. - Idempotent operations make retries easier; use idempotency keys if needed.
- Avoid mixing heavy Topic operations with large SQL reads in a single transaction unless necessary.