为什么推迟回滚?

时间:2017-09-26 08:39:13

标签: go transactions

我已经开始使用Go进行网络服务并进行一些数据库交互(惊喜!!!),我找到了这个例子:

tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}
defer tx.Rollback()
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close() // danger!
for i := 0; i < 10; i++ {
    _, err = stmt.Exec(i)
    if err != nil {
        log.Fatal(err)
    }
}
err = tx.Commit()
if err != nil {
    log.Fatal(err)
}
// stmt.Close() runs here!

来自http://go-database-sql.org/prepared.html

这个例子很容易理解。但是,它给我留下了一个悬而未决的问题。为什么defer事务回滚调用?

为什么不执行以下操作:

err := tx.Commit()

if err != nil {
    log.Error(err)
    tx.Rollback()
}

defer tx.Rollback()不会总是尝试回滚吗?即使tx.Commit()成功,或者我误解了defer的某些内容?

2 个答案:

答案 0 :(得分:5)

重要的是,如果您推迟 tx.Rollback(),即使您提早返回,也可以确保它会被调用,而“窍门”就是调用{{1} }在已提交的事务上实际上不会进行回滚,因为一旦事务被提交,它就会被提交并且无法回滚:) 因此,这是使代码保持简单的巧妙技巧。

答案 1 :(得分:1)

这个例子有点误导。它使用log.Fatal(err)进行错误处理。你通常不这样做,而是return err。因此,延迟回滚用于确保在提前返回时回滚事务。