gorm 事务的使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: gorm 事务的使用

gorm事务默认是开启的。为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。

如果没有这方面的要求,您可以在初始化时禁用它,这将获得大约 30%+ 性能提升。

一般不推荐禁用

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

普通事务

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  db.Transaction(func(tx *gorm.DB) error {
    // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
    if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
      // 返回任何错误都会回滚事务
      return err
    }
    if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
      return err
    }
    // 返回 nil 提交事务
    return nil
  })
}

执行下面代码,其中执行返回了一个test for err的错误,此时事务自动回滚,数据表中无数据

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  flag := false
  err := db.Transaction(func(tx *gorm.DB) error {
    // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
    if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
      // 返回任何错误都会回滚事务
      return err
    }
    if !flag {
      return errors.New("test for err")
    }
    if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
      return err
    }
    // 返回 nil 提交事务
    return nil
  })
  if err != nil {
    fmt.Println(err)//test for err
  }
}

嵌套事务

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

在下面代码中,我们知道包含name2的事务返回了err,是会回滚的,而外层事务返回nil,则会提交

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  db.Transaction(func(tx *gorm.DB) error {
    tx.Create(&TMG{Name: "name 1"})
    tx.Transaction(func(tx2 *gorm.DB) error {
      tx2.Create(&TMG{Name: "name 2"})
      return errors.New("rollback user2") // Rollback user2
    })
    tx.Transaction(func(tx2 *gorm.DB) error {
      tx2.Create(&TMG{Name: "name 3"})
      return nil
    })
    return nil
  })
}


手动事务

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 开始事务
  tx := db.Begin()
  // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
  tx.Create(&TMG{Name: "wxf1"})
  tx.Create(&TMG{Name: "wxf2"})
  tx.Create(&TMG{Name: "wxf3"})
  // ...
  ...
  if err!=nil{
    // 遇到错误时回滚事务
    fmt.Println(tx.Rollback().Error)
  }
  ...
  // 否则,提交事务
  fmt.Println(tx.Commit().Error)
}

一个特殊的示例

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 事务
  CreateTMG(db)
}
func CreateTMG(db *gorm.DB) error {
  // 再唠叨一下,事务一旦开始,你就应该使用 tx 处理数据
  tx := db.Begin()
  defer func() {
    if r := recover(); r != nil {
      tx.Rollback()
    }
  }()
  if err := tx.Error; err != nil {
    return err
  }
  if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
    tx.Rollback()
    return err
  }
  if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
    tx.Rollback()
    return err
  }
  return tx.Commit().Error
}

SavePoint、RollbackTo

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

这里rollback到了sp1的位置,也就是说,数据库中只存了wxf666这条数据

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 事务
  tx := db.Begin()
  tx.Create(&TMG{Name: "wxf666"})
  tx.SavePoint("sp1")
  tx.Create(&TMG{Name: "wxf777"})
  tx.Create(&TMG{Name: "wxf888"})
  tx.SavePoint("sp2")
  tx.RollbackTo("sp1")
  tx.Commit()
}


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8月前
|
SQL 数据库 索引
gorm普通的增删改查
gorm普通的增删改查
76 0
|
8月前
|
SQL 数据库
GORM—删
GORM—删
86 0
|
8月前
|
SQL 数据库
GORM—增
GORM—增
63 0
|
8月前
|
SQL 数据库
GORM—查
GORM—查
69 0
|
8月前
|
SQL
GORM—改
GORM—改
43 0
|
关系型数据库 MySQL 数据库
GORM V2 读操作
GORM V2 读操作
56 1
|
SQL 安全 数据库
GORM V2 写操作
GORM V2 写操作
67 0
|
SQL
GORM中使用事务
GORM中使用事务
149 0
|
Go
GORM v2 一对一关联查询使用(Belongs To 、Has One)
GORM v2 一对一关联查询使用(Belongs To 、Has One)
442 0
GORM v2 一对一关联查询使用(Belongs To 、Has One)
|
SQL
gorm批量插入解决方案
gorm批量插入解决方案
1084 0
gorm批量插入解决方案

热门文章

最新文章