中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決Mysql分布式事務問題

發布時間:2021-12-04 10:09:44 來源:億速云 閱讀:193 作者:iii 欄目:云計算

本篇內容介紹了“如何解決Mysql分布式事務問題”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

背景

2020 年 4 月,我們開始嘗試實現 go 語言的分布式事務框架 Seata-Golang。眾所周知,Seata AT 模式以無業務代碼侵入的特點,被廣大開發者推崇。Java 版 Seata AT 模式通過對 DataSource 數據源進行代理,在 sql 語句執行時,對 sql 攔截解析,獲取數據庫對應數據在 sql 語句執行前后的副本,序列化后保存起來,在 TC 協調回滾時用來回滾對應數據。實現 go 版本 client 的 AT 模式時,怎樣對業務開發者更友好,入侵更少,成了首要考慮的目標。

如何解決Mysql分布式事務問題

使用 go 操作數據庫時,我們會使用到 go 語言的官方庫 database/sql,通過 sql.Open("mysql", ${dsn}) 獲取一個數據源操作對象 db。開啟事務時,使用 db.Begin() 或 db.BeginTx(ctx, &sql.TxOptions{}) 獲得事務操作對象 tx,執行 sql 查詢使用 tx.Query;執行 sql 新增、修改、刪除,使用 tx.Exec;最后使用 tx.Commit() 提交或使用 tx.Rollback() 回滾。

go 語言官方庫 database/sql 提供了一個標準抽象層,通過實現不同的 driver 一套標準的抽象 API 可以操作不同的數據庫。開發 Go 版本的 AT 模式,必然要兼容 database/sql。通過研究 database/sql 的 api,創建數據源操作對象,數據庫有關的配置必須通過 Data Source Name (DSN) 抽象傳遞進去,下面是 DSN 的定義:

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...?mN=valueN]

實現 AT 模式對數據源代理是需要和事務協調器 TC 進行交互的,如果將 AT 模式實現在 driver 層,那么和 TC 交互的一些參數必須要通過 DSN 傳遞到 driver,這樣有些破壞它的設計。所以,最后采取了一種折中方案,在 database/sql 層之上實現 AT 模式,代理 database/sql 創建出來的數據源操作對象。數據源代理對象實現 database/sql 庫定義的 Tx 接口,另外再提供一個開啟事務的方法:Begin(),雖然沒有完全兼容 database/sql 的 api,但是關鍵接口和它的定義成一樣,勉強還能接受。到此,Seata-Golang 項目核心功能的開發已完成。

type Tx interface {
    Commit() error
    Rollback() error
}

轉折

Seata-Golang 開源后,逐漸被一些開發者了解和接觸,社區也對 Seata-Golang 發出了一些反饋的聲音,不少開發者并不習慣寫原生 sql,他們希望將 Seata-Golang 集成到 ORM 框架,因為當時的設計沒有完全兼容 database/sql 導致集成上遇到一些困難。隨著社區的熱切呼喚,且得益于前期對 driver 的一些研究,念念不忘必有回響,今年 3 月突然靈感迸發:為什么參數一定要通過 DSN 傳遞?Seata-Golang Client 初始化后,在需要時通過 Client 端的 API config.GetATConfig() 直接獲取使用不就可以了。

如何解決Mysql分布式事務問題

于是工作之余,歷時 2 周開發,第一個集成 Seata-Golang 的完全兼容 database/sql 的 mysql driver 被開發出來

driver 的一些細節

  • 使用該 driver 進行分布式事務操作時,不能在 dsn 中設置 interpolateParams 參數為 true

這涉及到 mysql 的兩個協議:Text 協議和 Binary 協議。有關兩個協議的區別,可以在文末參考文檔找到資料。實現該 driver 只對 binary 協議進行了處理,開啟 interpolateParams 會使用 text 協議執行 sql。

  • 使用該 driver 在需要加入全局事務組和 tc 進行交互時,需要使用 db.BeginTx(ctx context.Context, opts driver.TxOptions) 方法,并在 ctx 中加入 XID 全局事務 id 的值

ctx := context.WithValue(context.Background(), mysql.XID, c.Request.Header.Get("XID"))
tx, err := dao.BeginTx(ctx, &sql.TxOptions{
        Isolation: sql.LevelDefault,
        ReadOnly:  false,
    })

XID 傳遞到 driver 層,會保存在 &mysqlConn 連接對象中,在和 TC 交互時用到。

  • 使用該 driver 的分布式事務功能前需要先初始化 seata-golang client 和 mysql driver

config.InitConf(configPath)
  client.NewRpcClient()
  mysql.InitDataResourceManager()
  mysql.RegisterResource(config.GetATConfig().DSN)

“如何解決Mysql分布式事務問題”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

青田县| 北碚区| 保山市| 雷州市| 新巴尔虎左旗| 滨海县| 会昌县| 华容县| 白城市| 东乌珠穆沁旗| 易门县| 临沂市| 鄂托克前旗| 万荣县| 华亭县| 民县| 阿图什市| 宜都市| 灌阳县| 广河县| 湘阴县| 大邑县| 卢龙县| 建水县| 舟曲县| 花莲县| 阿巴嘎旗| 潮州市| 兰考县| 剑河县| 临高县| 庆城县| 永靖县| 南雄市| 新乡县| 自治县| 蒙山县| 沂南县| 文化| 吉隆县| 称多县|