禁用默认事务

为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,您可以在初始化时禁用它,这将获得大约 30%+ 性能提升。

1. // 全局禁用
2. db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
3. SkipDefaultTransaction: true,
4. })

6. // 持续会话模式
7. tx := db.Session(&Session{SkipDefaultTransaction: true})
8. tx.First(&user, 1)
9. tx.Find(&users)
10. tx.Model(&user).Update("Age", 18)

事务

要在事务中执行一系列操作,一般流程如下:

1. db.Transaction(func(tx *gorm.DB) error {
2. // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
3. if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
4. // 返回任何错误都会回滚事务
5. return err
6. }

8. if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
9. return err
10. }

12. // 返回 nil 提交事务
13. return nil
14. })

嵌套事务

GORM 支持嵌套事务,您可以回滚较大事务内执行的一部分操作,例如:

1. db.Transaction(func(tx *gorm.DB) error {
2. tx.Create(&user1)

4. tx.Transaction(func(tx2 *gorm.DB) error {
5. tx2.Create(&user2)
6. return errors.New("rollback user2") // Rollback user2
7. })

9. tx.Transaction(func(tx2 *gorm.DB) error {
10. tx2.Create(&user3)
11. return nil
12. })

14. return nil
15. })

17. // Commit user1, user3

手动事务

Gorm 支持直接调用事务控制方法(commit、rollback),例如:

1. // 开始事务
2. tx := db.Begin()

4. // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
5. tx.Create(...)

7. // ...

9. // 遇到错误时回滚事务
10. tx.Rollback()

12. // 否则,提交事务
13. tx.Commit()

一个特殊的示例

1. func CreateAnimals(db *gorm.DB) error {
2. // 再唠叨一下,事务一旦开始,你就应该使用 tx 处理数据
3. tx := db.Begin()
4. defer func() {
5. if r := recover(); r != nil {
6. tx.Rollback()
7. }
8. }()

10. if err := tx.Error; err != nil {
11. return err
12. }

14. if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
15. tx.Rollback()
16. return err
17. }

19. if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
20. tx.Rollback()
21. return err
22. }

24. return tx.Commit().Error
25. }

SavePoint、RollbackTo

GORM 提供了 SavePoint、Rollbackto 方法,来提供保存点以及回滚至保存点功能,例如:

1. tx := db.Begin()
2. tx.Create(&user1)

4. tx.SavePoint("sp1")
5. tx.Create(&user2)
6. tx.RollbackTo("sp1") // Rollback user2

8. tx.Commit() // Commit user1