Database Transaction
Transactions are a fundamental concept of all database systems. The essential point of a transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all.
Mango SQL Transaction
To make developer life easier, Mango SQL natively support transaction.
go
// if one request fail, both will be rollback
err := db.Transaction(func(tx *DBClient) error {
_, err1 := tx.User.Upsert(UserUpdate{Id: 1, Name: "usernew"})
_, err2 = tx.User.Upsert(UserUpdate{Id: 2, Name: "user1-updated"})
return errors.Join(err1, err2)
})
go
// if one request fail, the other may still modify the database
_, err1 := db.User.Upsert(UserUpdate{Id: 1, Name: "usernew"})
_, err2 = db.User.Upsert(UserUpdate{Id: 2, Name: "user1-updated"})
return errors.Join(err1, err2)
Reusable Parameter
To make code more reusable, Mango SQL use the same object *DBClient
for normal and transaction. No need to handle multiple signature like sql.Db
and sql.Tx
go
func AppendLog(db *DBClient, msg string) error {
_, err := db.Log.Insert(LogCreate{ Msg: msg })
return err
}
func main() {
// can be called directly with db
AppendLog(db, "Hello")
err := db.Transaction(func(tx *DBClient) error {
// also accept to be called in a transaction
return AppendLog(tx, "Hello")
})
}
WARNING
Nested Transactions are not supported