检测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中文网其他相关文章!