How does context cancellation work with database/sql, including transactions and rows?
Question 279HardGo 1.22 to 1.25
Use the *Context methods: QueryContext, ExecContext, QueryRowContext, BeginTx, PingContext, and Conn(ctx). When the context is canceled:
- A call waiting for a pool connection returns straight away with the context error.
- For a running query,
database/sqltells the driver to cancel. For example,pgx/lib/pqsend a Postgres cancel request, and MySQL may kill the query or close the connection. Whether the server actually stops depends on the driver. Rowstied to that context are closed automatically, androws.Next()returns false withrows.Err()reporting the context error. Always checkrows.Err().- For
BeginTx(ctx, ...): "If the context is canceled, the sql package will roll back the transaction. Tx.Commit will return an error."
func transfer(ctx context.Context, db *sql.DB, from, to int64, amt int) (err error) {
tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
if err != nil {
return err
}
defer func() {
if err != nil {
_ = tx.Rollback() // harmless if already rolled back
}
}()
if _, err = tx.ExecContext(ctx, `UPDATE acct SET bal = bal - $1 WHERE id = $2`, amt, from); err != nil {
return err
}
if _, err = tx.ExecContext(ctx, `UPDATE acct SET bal = bal + $1 WHERE id = $2`, amt, to); err != nil {
return err
}
return tx.Commit()
}
Gotcha: if cancellation arrives while Commit is on the wire, the client may not know whether the commit happened. Critical operations need idempotency keys.
More on Context
- Q277When exactly is an http.Request's context canceled on the server side, and how do you use it correctly?
- Q278On the HTTP client side, how does context interact with http.Client.Timeout and response bodies?
- Q280Write a function that runs a blocking call with a context and returns early on cancellation. What goroutine leak must you avoid?
- Q281How should a long-running worker loop respect cancellation? Discuss select fairness and CPU-bound loops.
- Q282How does errgroup.WithContext use context, and what is a common bug with it?
- Q283How would you merge two contexts so the result is canceled when either one is?