I have started using Go for a web-service and have some database interaction (surprise!!!) and I have found this example:
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!
From http://go-database-sql.org/prepared.html
The example is well formulated an easy to understand. However, it leaves me with an unanswered question. Why defer
the transaction Rollback call?
Why not just do the following:
err := tx.Commit()
if err != nil {
log.Error(err)
tx.Rollback()
}
Would defer tx.Rollback()
not always attempt a rollback? Even if tx.Commit()
was a success, or have I misunderstood something about defer
?
ROLLBACK is a transactional control language in SQL. It lets a user undo those transactions that aren't saved yet in the database. One can make use of this command if they wish to undo any changes or alterations since the execution of the last COMMIT.
You can use ROLLBACK TRANSACTION to erase all data modifications made from the start of the transaction or to a savepoint. It also frees resources held by the transaction. This does not include changes made to local variables or table variables.
COMMIT permanently saves the changes made by the current transaction. ROLLBACK undo the changes made by the current transaction. 2. The transaction can not undo changes after COMMIT execution.
If a rollback fails, then you would have a serious problem. The reliability of the database cannot be guaranteed. In other words; you probably have some sort of corruption in your transaction log and will end up with an inconsistent database.
The important thing is that if you defer tx.Rollback()
you are sure that it will be called even if you do an early return and the "trick" is that calling tx.Rollback()
on a committed transaction will not actually do the rollback, because once a transaction is committed, it's committed and there is no way to roll it back :)
So this is a neat trick on how to keep the code simple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With