首页 > 后端开发 > Golang > 如何在 Go 的 `database/sql` 包中可靠地检测数据库事务提交或回滚?

如何在 Go 的 `database/sql` 包中可靠地检测数据库事务提交或回滚?

Patricia Arquette
发布: 2024-12-22 18:44:11
原创
649 人浏览过

How Can I Reliably Detect Database Transaction Commit or Rollback in Go's `database/sql` Package?

检测database/sql中的事务提交或回滚

在database/sql包及其驱动接口和Tx类型中,它不是明确可以确定事务是否已提交或回滚,而无需尝试另一个事务。然后可以检查后续尝试返回的错误以推断事务的状态。

为了避免额外的开销,可以考虑在提交或回滚后将 Tx 变量设置为 nil。但是,通常不鼓励这种方法,因为它可能会导致意外行为和内存泄漏。

推荐的解决方案是使用事务处理程序来包装事务逻辑。这可确保 Begin()、Commit() 和 Rollback() 调用始终在同一函数内,从而简化跟踪并确保使用 defer 语句进行正确的事务处理。

例如:

func Transact(db *sql.DB, txFunc func(*sql.Tx) error) (err error) {
    tx, err := db.Begin()
    if err != nil {
        return
    }
    defer func() {
        if p := recover(); p != nil {
            tx.Rollback()
            panic(p) // re-throw panic after Rollback
        } else if err != nil {
            tx.Rollback() // err is non-nil; don't change it
        } else {
            err = tx.Commit() // err is nil; if Commit returns error update err
        }
    }()
    err = txFunc(tx)
    return err
}
登录后复制

使用此处理程序,事务逻辑可以封装如下:

func (s Service) DoSomething() error {
    return Transact(s.db, func (tx *sql.Tx) error {
        if _, err := tx.Exec(...); err != nil {
            return err
        }
        if _, err := tx.Exec(...); err != nil {
            return err
        }
        return nil
    })
}
登录后复制

这种方法使事务代码简洁并确保处理的一致性。请注意,事务处理程序使用recover() 来拦截恐慌并立即启动回滚。但是,应该强调的是,返回错误优于恐慌。

以上是如何在 Go 的 `database/sql` 包中可靠地检测数据库事务提交或回滚?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板