Disable Default Transaction

GORM perform write (create/update/delete) operations run inside a transaction to ensure data consistency, you can disable it during initialization if it is not required, you will gain about 30%+ performance improvement after that

  1. // Globally disable
  2. db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
  3. SkipDefaultTransaction: true,
  4. })
  5. // Continuous session mode
  6. tx := db.Session(&Session{SkipDefaultTransaction: true})
  7. tx.First(&user, 1)
  8. tx.Find(&users)
  9. tx.Model(&user).Update("Age", 18)

Transaction

To perform a set of operations within a transaction, the general flow is as below.

  1. db.Transaction(func(tx *gorm.DB) error {
  2. // do some database operations in the transaction (use 'tx' from this point, not 'db')
  3. if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
  4. // return any error will rollback
  5. return err
  6. }
  7. if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
  8. return err
  9. }
  10. // return nil will commit the whole transaction
  11. return nil
  12. })

Nested Transactions

GORM supports nested transactions, you can rollback a subset of operations performed within the scope of a larger transaction, for example:

  1. db.Transaction(func(tx *gorm.DB) error {
  2. tx.Create(&user1)
  3. tx.Transaction(func(tx2 *gorm.DB) error {
  4. tx2.Create(&user2)
  5. return errors.New("rollback user2") // Rollback user2
  6. })
  7. tx.Transaction(func(tx3 *gorm.DB) error {
  8. tx3.Create(&user3)
  9. return nil
  10. })
  11. return nil
  12. })
  13. // Commit user1, user3

Control the transaction manually

Gorm supports calling transaction control functions (commit / rollback) directly, for example:

  1. // begin a transaction
  2. tx := db.Begin()
  3. // do some database operations in the transaction (use 'tx' from this point, not 'db')
  4. tx.Create(...)
  5. // ...
  6. // rollback the transaction in case of error
  7. tx.Rollback()
  8. // Or commit the transaction
  9. tx.Commit()

A Specific Example

  1. func CreateAnimals(db *gorm.DB) error {
  2. // Note the use of tx as the database handle once you are within a transaction
  3. tx := db.Begin()
  4. defer func() {
  5. if r := recover(); r != nil {
  6. tx.Rollback()
  7. }
  8. }()
  9. if err := tx.Error; err != nil {
  10. return err
  11. }
  12. if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
  13. tx.Rollback()
  14. return err
  15. }
  16. if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
  17. tx.Rollback()
  18. return err
  19. }
  20. return tx.Commit().Error
  21. }

SavePoint, RollbackTo

GORM provides SavePoint, RollbackTo to save points and roll back to a savepoint, for example:

  1. tx := db.Begin()
  2. tx.Create(&user1)
  3. tx.SavePoint("sp1")
  4. tx.Create(&user2)
  5. tx.RollbackTo("sp1") // Rollback user2
  6. tx.Commit() // Commit user1