• 如何优雅的使用 GORM 来实现 MySQL 事务


    前言

    为了确保数据一致性,在项目中会经常用到事务处理,回滚操作还是比较常见的需求;事务处理可以用来维护数据库的完整性,保证成批的sql语句要么全部都执行,要么全不执行,对于MySQL事务相信大家应该都不陌生,这篇文章主要总结一下在Go语言中Gorm是如何实现事务的;感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

    禁用默认事务

    gorm事务默认是开启的。为了确保数据一致性,Gorm会在事务里执行写入操作(增删改)。

    如果对数据一致性要求不高的话,可以在初始化时禁用它,性能将提升大约30%。

    一般不推荐禁用。

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

    自动事务

    通过db.Transaction函数实现事务,如果闭包函数返回错误,则回滚事务。

    1. db.Transaction(func(tx *gorm.DB) error {
    2. // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db'
    3. if err := tx.Create(&User{Name: "Lili"}).Error; err != nil {
    4. // 返回任何错误都会回滚事务
    5. return err
    6. }
    7. if err := tx.Create(&User{Name: "xiaoming"}).Error; err != nil {
    8. return err
    9. }
    10. // 返回 nil 提交事务
    11. return nil
    12. })
    13. 复制代码

    手动事务

    在开发中经常需要数据库事务来保证多个数据库写操作的原子性。例如电商系统中的扣减库存和保存订单。

    gorm事务用法:

    1. // 开启事务
    2. tx := db.Begin()
    3. //在事务中执行数据库操作,使用的是tx变量,不是db。
    4. //库存减一
    5. //等价于: UPDATE `goods` SET `stock` = stock - 1 WHERE `goods`.`id` = '2' and stock > 0
    6. //RowsAffected用于返回sql执行后影响的行数
    7. rowsAffected := tx.Model(&goods).Where("stock > 0").Update("stock", gorm.Expr("stock - 1")).RowsAffected
    8. if rowsAffected == 0 {
    9. //如果更新库存操作,返回影响行数为0,说明没有库存了,结束下单流程
    10. //这里回滚作用不大,因为前面没成功执行什么数据库更新操作,也没什么数据需要回滚。
    11. //这里就是举个例子,事务中可以执行多个sql语句,错误了可以回滚事务
    12. tx.Rollback()
    13. return
    14. }
    15. err := tx.Create(保存订单).Error
    16. //保存订单失败,则回滚事务
    17. if err != nil {
    18. tx.Rollback()
    19. } else {
    20. tx.Commit()
    21. }
    22. 复制代码

    嵌套事务

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

    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(tx2 *gorm.DB) error {
    8. tx2.Create(&user3)
    9. return nil
    10. })
    11. return nil
    12. })
    13. // Commit user1, user3
    14. 复制代码

    SavePoint、RollbackTo

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

    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
    7. 复制代码

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

    小结

    关于Go GORM 事务详细介绍的文章就介绍到这了,总的来说Gorm事务的实现非常简单,go语言操作mysql事务主要用到了三个函数:

    • Db.Begin() 开始事务
    • Db.Commit() 提交事务
    • Db.Rollback() 回滚事务


     

  • 相关阅读:
    Docker GitLab-Runner安装
    【React】AntD组件的使用--极客园--02.登录模块
    【Windows系统5分钟搭建Linux环境】
    Shiro【散列算法、Shiro会话、退出登录 、权限表设计、注解配置鉴权 】(五)-全面详解(学习总结---从入门到深化)
    前端一句代码查看页面溢出
    Java分库分表/读写分离
    JTS: 17 DiscreteHausdorffDistance 豪斯多夫距离计算
    error: tool or SDK not found:
    深入理解Linux2.6内核中sys_mmap系统调用
    家政服务小程序,家政维修系统,专业家政软件开发商;家政服务小程序,家政行业软件开发
  • 原文地址:https://blog.csdn.net/Trouvailless/article/details/126761524