详解如何利用GORM实现MySQL事务

目录
  • 前言
  • 禁用默认事务
  • 自动事务
  • 手动事务
  • 嵌套事务
  • SavePoint、RollbackTo
  • 小结

前言

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

禁用默认事务

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

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

一般不推荐禁用。

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

自动事务

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

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

  if err := tx.Create(&User{Name: "xiaoming"}).Error; err != nil {
    return err
  }

  // 返回 nil 提交事务
  return nil
})

手动事务

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

gorm事务用法:

// 开启事务
tx := db.Begin()

//在事务中执行数据库操作,使用的是tx变量,不是db。

//库存减一
//等价于: UPDATE `goods` SET `stock` = stock - 1  WHERE `goods`.`id` = '2' and stock > 0
//RowsAffected用于返回sql执行后影响的行数
rowsAffected := tx.Model(&goods).Where("stock > 0").Update("stock", gorm.Expr("stock - 1")).RowsAffected
if rowsAffected == 0 {
    //如果更新库存操作,返回影响行数为0,说明没有库存了,结束下单流程
    //这里回滚作用不大,因为前面没成功执行什么数据库更新操作,也没什么数据需要回滚。
    //这里就是举个例子,事务中可以执行多个sql语句,错误了可以回滚事务
    tx.Rollback()
    return
}
err := tx.Create(保存订单).Error

//保存订单失败,则回滚事务
if err != nil {
    tx.Rollback()
} else {
    tx.Commit()
}

嵌套事务

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

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

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

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

  return nil
})

// Commit user1, user3

SavePoint、RollbackTo

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

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

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

tx.Commit() // Commit user1

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

小结

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

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

到此这篇关于详解如何利用GORM实现MySQL事务的文章就介绍到这了,更多相关Golang GORM实现MySQL事务内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • gORM操作MySQL的实现

    ORM 框架 ORM:Object  Relational   Mapping  -- 对象关系映射. 作用: 通过操作结构体对象,来达到操作数据库表的目的. 通过结构体对象,来生成数据库表. 优点: SQL有可能 比较复杂.(Oracle --- 子查询 -- 嵌套)ORM 操作数据库,不需要使用 SQL 不同开发者,书写的 SQL 语句执行效率不同. go语言支持的 ORM: gORM:gORM中文文档 xORM: gorm 连接数据库.建表 回顾MySQL 确认mysql服务启动: ps

  • golang gorm 操作mysql及gorm基本用法

    golang 官方的那个操作mysql的有点麻烦所以就使用了gorm,下面就gorm的使用做下简单介绍 下载gorm: go get -u github.com/jinzhu/gorm 在项目中引入gorm: import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) 定义db连接信息 func DbConn(MyUser, Password, Host, Db stri

  • gorm操作MySql数据库的方法

    1.表中字段区分大小写的设置 在使用gorm查询的时候,会出现账户名A和a是一样的情况,是因为mysql默认不区分大小写造成的 1.问题产生的原因 MySQL在Windows下都不区分大小写. MySQL在Linux下数据库名.表名.列名.别名大小写规则是这样的: 1.数据库名与表名是严格区分大小写的: 2.表的别名是严格区分大小写的: 3.列名与列的别名在所有的情况下均是忽略大小写的: 4.变量名也是严格区分大小写的: MySQL在查询字符串时是大小写不敏感的,在编绎MySQL时一般以ISO-

  • 详解如何利用GORM实现MySQL事务

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

  • 详解如何利用Xtrabackup进行mysql增量备份

    目录 利用Xtrabackup进行mysql增量备份 安装 设置数据库用于备份账户 全量备份 增量备份 提问总结 原理 为什么最后一次增量备份不用 "--apply-log-only" 为什么备份完后要准备备份 "prepare" 为什么选择这个做备份? 利用Xtrabackup进行mysql增量备份 现在xtrabackup版本升级到了8.0,但是只对mysql8.0才有支持, 我们这还是使用2.4, 但是2.4相比之前的2.1有了比较大的变化:innobacku

  • 详解Swift 利用Opration和OprationQueue来下载网络图片

    详解Swift 利用Opration和OprationQueue来下载网络图片 1. 基于Opration封装的获取网络数据组件 import Foundation import UIKit public typealias OpreationClosure = ((_ data:Data? , _ error: Error?) -> Void) class LJOpreationManager: Operation { /** * 下载用的url */ public var imageUrl

  • 详解IOS 利用storyboard修改UITextField的placeholder文字颜色

    详解IOS 利用storyboard修改UITextField的placeholder文字颜色 最近有个需求需要修改UITextField的placeholder文字颜色,在网上找发现有用代码修改的,但是考虑到更加优雅的实现,所以尝试着在storyboard中直接实现,结果竟然真的成功了, 实现的位置如下: 具体步骤: 1.在User Defined Runtime Attributes中添加一个Key. 2.输入Key Path(这里我们输入_placeholderLabel.textColo

  • 详解Python利用configparser对配置文件进行读写操作

    简介 想写一个登录注册的demo,但是以前的demo数据都写在程序里面,每一关掉程序数据就没保存住.. 于是想着写到配置文件里好了 Python自身提供了一个Module - configparser,来进行对配置文件的读写 Configuration file parser. A configuration file consists of sections, lead by a "[section]" header, and followed by "name: valu

  • 详解如何利用tushare、pycharm和excel三者结合进行股票分析

    前言 当你逐渐了解tushare之后,你会发现我们要进行数据分析只靠tushare是不够的,接下来我将介绍如何利用第三方软件将tushare获取的数据进行分析. 一.使用工具 首先我们需要下载pycharm,下载网址:https://www.jetbrains.com/pycharm/download/,同时准备两个Excel文件,一个用了存放获取的数据,另一个进行数据的引用与分析. 二.使用步骤 1.首先在pycharm的setting中下载三个包:numpy.tushare.matplotl

  • 详解Java使用JDBC连接MySQL数据库

    一:什么是数据库,为什么要有数据库? 数据,数据库,数据库管理系统和数据库系统是与数据库技术密切相关的四个基本概念. 数据库相信大家都耳熟能详了,其实数据库顾名思义就是存放数据的仓库,只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的~ 可能有朋友就要打断我施法了,停停停,我们Java程序猿在IDEA里面和控制台你侬我侬,没有对象new个对象存储在内存JVM的堆上就行了,学数据库干啥啊? 这时候我们就需要了解到:内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运

  • 详解Java利用深度优先遍历解决迷宫问题

    目录 什么是深度优先 一个简单的例子 程序实现 什么是深度优先 什么是深度,即向下,深度优先,即向下优先,一口气走到底,走到底发现没路再往回走. 在算法实现上来讲,深度优先可以考虑是递归的代名词,深度优先搜索必然需要使用到递归的思路. 有的人可能会说了,我可以用栈来实现,以迭代的方式,那么问题来了,栈这种数据结构,同学们认为是否也囊括了递归呢?Java语言的方法区本身也是实现在一个栈空间上的. 一个简单的例子 我们以一个简单的迷宫为例,以1代表墙,0代表路径,我们构造一个具有出入口的迷宫. 1

  • 详解如何利用Python绘制迷宫小游戏

    目录 构思 绘制迷宫 走出迷宫 完整代码 更大的挑战 关于坐标系设置 周末在家,儿子闹着要玩游戏,让玩吧,不利于健康,不让玩吧,扛不住他折腾,于是想,不如一起搞个小游戏玩玩! 之前给他编过猜数字 和 掷骰子 游戏,现在已经没有吸引力了,就对他说:“我们来玩个迷宫游戏吧.” 果不其然,有了兴趣,于是和他一起设计实现起来,现在一起看看我们是怎么做的吧,说不定也能成为一个陪娃神器~ 先一睹为快: 构思 迷宫游戏,相对比较简单,设置好地图,然后用递归算法来寻找出口,并将过程显示出来,增强趣味性. 不如想

  • 详解Python利用APScheduler框架实现定时任务

    目录 背景 样例代码 代码详解 执行结果 知识点补充 背景 最近在做一些python工具的时候,常常会碰到定时器问题,总觉着使用threading.timer或者schedule模块非常不优雅.所以这里给自己做个记录,也分享一个定时任务框架APScheduler.具体的架构原理就不细说了,用个例子说明一下怎么简易的使用. 样例代码 先上样例代码,如下: #!/user/bin/env python # coding=utf-8 """ @project : csdn @aut

随机推荐