我报名参与金石方案1期应战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情
前言
为了保证数据一致性,在项目中会常常用到业务处理,回滚操作还是比较常见的需求;业务处理能够用来保护数据库的完整性,保证成批的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() 回滚业务