詳解如何利用GORM實(shí)現(xiàn)MySQL事務(wù)
前言
為了確保數(shù)據(jù)一致性,在項(xiàng)目中會(huì)經(jīng)常用到事務(wù)處理,回滾操作還是比較常見(jiàn)的需求;事務(wù)處理可以用來(lái)維護(hù)數(shù)據(jù)庫(kù)的完整性,保證成批的sql語(yǔ)句要么全部都執(zhí)行,要么全不執(zhí)行,對(duì)于MySQL事務(wù)相信大家應(yīng)該都不陌生,這篇文章主要總結(jié)一下在Go語(yǔ)言中Gorm是如何實(shí)現(xiàn)事務(wù)的;感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
禁用默認(rèn)事務(wù)
gorm事務(wù)默認(rèn)是開(kāi)啟的。為了確保數(shù)據(jù)一致性,Gorm會(huì)在事務(wù)里執(zhí)行寫(xiě)入操作(增刪改)。
如果對(duì)數(shù)據(jù)一致性要求不高的話,可以在初始化時(shí)禁用它,性能將提升大約30%。
一般不推薦禁用。
// 全局禁用 db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{ SkipDefaultTransaction: true, })
自動(dòng)事務(wù)
通過(guò)db.Transaction函數(shù)實(shí)現(xiàn)事務(wù),如果閉包函數(shù)返回錯(cuò)誤,則回滾事務(wù)。
db.Transaction(func(tx *gorm.DB) error { // 在事務(wù)中執(zhí)行一些 db 操作(從這里開(kāi)始,您應(yīng)該使用 'tx' 而不是 'db') if err := tx.Create(&User{Name: "Lili"}).Error; err != nil { // 返回任何錯(cuò)誤都會(huì)回滾事務(wù) return err } if err := tx.Create(&User{Name: "xiaoming"}).Error; err != nil { return err } // 返回 nil 提交事務(wù) return nil })
手動(dòng)事務(wù)
在開(kāi)發(fā)中經(jīng)常需要數(shù)據(jù)庫(kù)事務(wù)來(lái)保證多個(gè)數(shù)據(jù)庫(kù)寫(xiě)操作的原子性。例如電商系統(tǒng)中的扣減庫(kù)存和保存訂單。
gorm事務(wù)用法:
// 開(kāi)啟事務(wù) tx := db.Begin() //在事務(wù)中執(zhí)行數(shù)據(jù)庫(kù)操作,使用的是tx變量,不是db。 //庫(kù)存減一 //等價(jià)于: UPDATE `goods` SET `stock` = stock - 1 WHERE `goods`.`id` = '2' and stock > 0 //RowsAffected用于返回sql執(zhí)行后影響的行數(shù) rowsAffected := tx.Model(&goods).Where("stock > 0").Update("stock", gorm.Expr("stock - 1")).RowsAffected if rowsAffected == 0 { //如果更新庫(kù)存操作,返回影響行數(shù)為0,說(shuō)明沒(méi)有庫(kù)存了,結(jié)束下單流程 //這里回滾作用不大,因?yàn)榍懊鏇](méi)成功執(zhí)行什么數(shù)據(jù)庫(kù)更新操作,也沒(méi)什么數(shù)據(jù)需要回滾。 //這里就是舉個(gè)例子,事務(wù)中可以執(zhí)行多個(gè)sql語(yǔ)句,錯(cuò)誤了可以回滾事務(wù) tx.Rollback() return } err := tx.Create(保存訂單).Error //保存訂單失敗,則回滾事務(wù) if err != nil { tx.Rollback() } else { tx.Commit() }
嵌套事務(wù)
GORM 支持嵌套事務(wù),可以回滾較大事務(wù)內(nèi)執(zhí)行的一部分操作,例如:
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 來(lái)提供保存點(diǎn)以及回滾至保存點(diǎn),例如:
tx := db.Begin() tx.Create(&user1) tx.SavePoint("sp1") tx.Create(&user2) tx.RollbackTo("sp1") // Rollback user2 tx.Commit() // Commit user1
這里rollback到了sp1的位置,也就是說(shuō),數(shù)據(jù)庫(kù)中只存了user1這條數(shù)據(jù)。
小結(jié)
關(guān)于Go GORM 事務(wù)詳細(xì)介紹的文章就介紹到這了,總的來(lái)說(shuō)Gorm事務(wù)的實(shí)現(xiàn)非常簡(jiǎn)單,go語(yǔ)言操作mysql事務(wù)主要用到了三個(gè)函數(shù):
- Db.Begin() 開(kāi)始事務(wù)
- Db.Commit() 提交事務(wù)
- Db.Rollback() 回滾事務(wù)
到此這篇關(guān)于詳解如何利用GORM實(shí)現(xiàn)MySQL事務(wù)的文章就介紹到這了,更多相關(guān)Golang GORM實(shí)現(xiàn)MySQL事務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GO?CountMinSketch計(jì)數(shù)器(布隆過(guò)濾器思想的近似計(jì)數(shù)器)
這篇文章主要介紹了GO?CountMinSketch計(jì)數(shù)器(布隆過(guò)濾器思想的近似計(jì)數(shù)器),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09GoLang日志監(jiān)控系統(tǒng)實(shí)現(xiàn)
這篇文章主要介紹了GoLang日志監(jiān)控系統(tǒng)的實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12Go中g(shù)routine通信與context控制實(shí)例詳解
隨著context包的引入,標(biāo)準(zhǔn)庫(kù)中很多接口因此加上了context參數(shù),下面這篇文章主要給大家介紹了關(guān)于Go中g(shù)routine通信與context控制的相關(guān)資料,需要的朋友可以參考下2022-02-02GO語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)的方法
這篇文章主要介紹了GO語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)的方法,實(shí)例分析了Go語(yǔ)言實(shí)現(xiàn)TCP服務(wù)的技巧,需要的朋友可以參考下2015-03-03