SQL事务中,BeginTx传入的context是否会作为全局默认生效?
Go语言事务中Context的传递规则
在Go的database/sql标准库中,BeginTx传入的context仅负责事务的初始化过程——比如创建事务时的连接获取、超时控制或取消逻辑,并不会自动覆盖后续事务内所有操作的context。
看你给出的两个示例:
- 第一个示例中的
tx.Prepare()不会监听BeginTx传入的ctx:
tx, _ := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable}) stmt, _ := tx.Prepare("SELECT id, timeout, lang FROM client WHERE id=?")
这个Prepare操作不会响应ctx的取消或超时信号,哪怕ctx被取消,该操作仍会继续执行直到完成或数据库端超时。
- 若要让事务内的操作也监听context,必须为每个操作显式调用带
Context后缀的方法并传入context,比如第二个示例的tx.PrepareContext(ctx):
tx, _ := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable}) stmt, _ := tx.PrepareContext(ctx, "SELECT id, timeout, lang FROM client WHERE id=?")
不止Prepare,事务内的Query、Exec、Commit、Rollback等操作都是同样的规则:
- 不带
Context后缀的方法(如tx.Query()、tx.Exec())不关联任何context,不受外部取消/超时影响 - 带
Context后缀的方法(如tx.QueryContext(ctx)、tx.ExecContext(ctx))才会绑定传入的context,当context触发取消或超时,对应的数据库操作会被中断
内容的提问来源于stack exchange,提问作者clarkk
相关产品推荐
相关产品推荐

