注意:此篇文章大部分內(nèi)容都是摘抄自 seata 的官網(wǎng)哲思,寫此篇文章的目的是對(duì)seata官網(wǎng)部分內(nèi)容總結(jié)拨扶,方便日后復(fù)習(xí)。
一魁亦、什么是seata
Seata 是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù)邀摆。Seata 將為用戶提供了 AT纵顾、TCC、SAGA 和 XA 事務(wù)模式栋盹,為用戶打造一站式的分布式解決方案施逾。其中AT
模式是Seata
主推的模式,是基于二階段提交來(lái)實(shí)現(xiàn)的例获。
術(shù)語(yǔ):
-
TC (Transaction Coordinator) 事務(wù)協(xié)調(diào)者
維護(hù)全局和分支事務(wù)的狀態(tài)汉额,驅(qū)動(dòng)全局事務(wù)提交或回滾。
-
TM (Transaction Manager) - 事務(wù)管理器
定義全局事務(wù)的范圍:開始全局事務(wù)躏敢、提交或回滾全局事務(wù)闷愤。
-
RM (Resource Manager) - 資源管理器
管理分支事務(wù)處理的資源,與TC交談以注冊(cè)分支事務(wù)和報(bào)告分支事務(wù)的狀態(tài)件余,并驅(qū)動(dòng)分支事務(wù)提交或回滾讥脐。
二、AT模式的介紹
AT模式需要保證每個(gè)業(yè)務(wù)庫(kù)啼器,都有一張undo_log
表旬渠,保存著業(yè)務(wù)數(shù)據(jù)執(zhí)行前和執(zhí)行后的鏡像數(shù)據(jù)。
1端壳、前提條件
- 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫(kù)告丢。
- Java 應(yīng)用,通過(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)损谦。
2岖免、整體機(jī)制
兩階段提交協(xié)議的演變:
- 一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個(gè)本地事務(wù)中提交,釋放本地鎖和連接資源照捡。
- 二階段:
- 提交異步化颅湘,非常快速地完成栗精。
- 回滾通過(guò)一階段的回滾日志進(jìn)行反向補(bǔ)償闯参。
3、讀寫隔離的實(shí)現(xiàn)
1悲立、寫隔離
- 一階段本地事務(wù)提交前鹿寨,需要確保先拿到 全局鎖 。
- 拿不到 全局鎖 薪夕,不能提交本地事務(wù)脚草。
- 拿 全局鎖 的嘗試被限制在一定范圍內(nèi),超出范圍將放棄原献,并回滾本地事務(wù)玩讳,釋放本地鎖涩蜘。
以一個(gè)示例來(lái)說(shuō)明:
兩個(gè)全局事務(wù) tx1 和 tx2嚼贡,分別對(duì) a 表的 m 字段進(jìn)行更新操作熏纯,m 的初始值 1000。
tx1 先開始粤策,開啟本地事務(wù)樟澜,拿到本地鎖,更新操作 m = 1000 - 100 = 900叮盘。本地事務(wù)提交前秩贰,先拿到該記錄的 全局鎖 ,本地提交釋放本地鎖柔吼。 tx2 后開始毒费,開啟本地事務(wù),拿到本地鎖愈魏,更新操作 m = 900 - 100 = 800觅玻。本地事務(wù)提交前,嘗試拿該記錄的 全局鎖 培漏,tx1 全局提交前溪厘,該記錄的全局鎖被 tx1 持有,tx2 需要重試等待 全局鎖 牌柄。
tx1 二階段全局提交畸悬,釋放 全局鎖 。tx2 拿到 全局鎖 提交本地事務(wù)珊佣。
如果 tx1 的二階段全局回滾蹋宦,則 tx1 需要重新獲取該數(shù)據(jù)的本地鎖,進(jìn)行反向補(bǔ)償?shù)母虏僮髦涠停瑢?shí)現(xiàn)分支的回滾冷冗。
此時(shí),如果 tx2 仍在等待該數(shù)據(jù)的 全局鎖虫碉,同時(shí)持有本地鎖贾惦,則 tx1 的分支回滾會(huì)失敗悬槽。分支的回滾會(huì)一直重試潮售,直到 tx2 的 全局鎖 等鎖超時(shí),放棄 全局鎖 并回滾本地事務(wù)釋放本地鎖逃呼,tx1 的分支回滾最終成功兢卵。
因?yàn)檎麄€(gè)過(guò)程 全局鎖 在 tx1 結(jié)束前一直是被 tx1 持有的习瑰,所以不會(huì)發(fā)生 臟寫 的問(wèn)題。
2秽荤、讀隔離
在數(shù)據(jù)庫(kù)本地事務(wù)隔離級(jí)別 讀已提交(Read Committed) 或以上的基礎(chǔ)上甜奄,Seata(AT 模式)的默認(rèn)全局隔離級(jí)別是 讀未提交(Read Uncommitted) 柠横。
如果應(yīng)用在特定場(chǎng)景下,必需要求全局的 讀已提交 课兄,目前 Seata 的方式是通過(guò) SELECT FOR UPDATE 語(yǔ)句的代理牍氛。
SELECT FOR UPDATE 語(yǔ)句的執(zhí)行會(huì)申請(qǐng) 全局鎖 ,如果 全局鎖 被其他事務(wù)持有烟阐,則釋放本地鎖(回滾 SELECT FOR UPDATE 語(yǔ)句的本地執(zhí)行)并重試搬俊。這個(gè)過(guò)程中,查詢是被 block 住的蜒茄,直到 全局鎖 拿到唉擂,即讀取的相關(guān)數(shù)據(jù)是 已提交 的,才返回檀葛。
出于總體性能上的考慮玩祟,Seata 目前的方案并沒(méi)有對(duì)所有 SELECT 語(yǔ)句都進(jìn)行代理,僅針對(duì) FOR UPDATE 的 SELECT 語(yǔ)句屿聋。
三空扎、事務(wù)分組
1、事務(wù)分組是什么胜臊?
事務(wù)分組是seata的資源邏輯勺卢,類似于服務(wù)實(shí)例。在file.conf中的my_test_tx_group就是一個(gè)事務(wù)分組象对『诔溃可以實(shí)現(xiàn)讓不同的微服務(wù)注冊(cè)到不同的組上。
2勒魔、通過(guò)事務(wù)分組如何找到后端集群甫煞?
- 首先程序中配置了事務(wù)分組(GlobalTransactionScanner 構(gòu)造方法的txServiceGroup參數(shù))
- 程序會(huì)通過(guò)用戶配置的配置中心去尋找service.vgroupMapping .[事務(wù)分組配置項(xiàng)],取得配置項(xiàng)的值就是TC集群的名稱
- 拿到集群名稱程序通過(guò)一定的前后綴+集群名稱去構(gòu)造服務(wù)名冠绢,各配置中心的服務(wù)名實(shí)現(xiàn)不同
- 拿到服務(wù)名去相應(yīng)的注冊(cè)中心去拉取相應(yīng)服務(wù)名的服務(wù)列表抚吠,獲得后端真實(shí)的TC服務(wù)列表
3、為什么這么設(shè)計(jì)弟胀,不直接取服務(wù)名楷力?
這里多了一層獲取事務(wù)分組到映射集群的配置。這樣設(shè)計(jì)后孵户,事務(wù)分組可以作為資源的邏輯隔離單位萧朝,出現(xiàn)某集群故障時(shí)可以快速failover,只切換對(duì)應(yīng)分組夏哭,可以把故障縮減到服務(wù)級(jí)別检柬,但前提也是你有足夠server集群。
4竖配、事物分組的例子
1何址、TC的異地多機(jī)房容災(zāi)
- 假定TC集群部署在兩個(gè)機(jī)房:guangzhou機(jī)房(主)和shanghai機(jī)房(備)各兩個(gè)實(shí)例
- 一整套微服務(wù)架構(gòu)項(xiàng)目:projectA
- projectA內(nèi)有微服務(wù):serviceA里逆、serviceB、serviceC 和 serviceD
其中用爪,projectA所有微服務(wù)的事務(wù)分組tx-transaction-group設(shè)置為:projectA原押,projectA正常情況下使用guangzhou的TC集群(主)
那么正常情況下,client端的配置如下所示:
seata.tx-service-group=projectA
seata.service.vgroup-mapping.projectA=Guangzhou
假如此時(shí)guangzhou集群分組整個(gè)down掉项钮,或者因?yàn)榫W(wǎng)絡(luò)原因projectA暫時(shí)無(wú)法與Guangzhou機(jī)房通訊班眯,那么我們將配置中心中的Guangzhou集群分組改為Shanghai,如下:
seata.service.vgroup-mapping.projectA=Shanghai
并推送到各個(gè)微服務(wù)烁巫,便完成了對(duì)整個(gè)projectA項(xiàng)目的TC集群動(dòng)態(tài)切換。
2宠能、單一環(huán)境多應(yīng)用接入
- 假設(shè)現(xiàn)在開發(fā)環(huán)境(或預(yù)發(fā)/生產(chǎn))中存在一整套seata集群
- seata集群要服務(wù)于不同的微服務(wù)架構(gòu)項(xiàng)目projectA亚隙、projectB、projectC
- projectA违崇、projectB阿弃、projectC之間相對(duì)獨(dú)立
我們將seata集群中的六個(gè)實(shí)例兩兩分組,使其分別服務(wù)于projectA羞延、projectB與projectC渣淳,那么此時(shí)seata-server端的配置如下(以nacos注冊(cè)中心為例):
registry {
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "DEFAULT_GROUP"
namespace = "8f11aeb1-5042-461b-b88b-d47a7f7e01c0"
#同理在其他幾個(gè)分組seata-server實(shí)例配置 project-b-group / project-c-group
cluster = "project-a-group"
username = "username"
password = "password"
}
}
client端的配置如下:
seata.tx-service-group=projectA
#同理,projectB與projectC配置 project-b-group / project-c-group
seata.service.vgroup-mapping.projectA=project-a-group
完成配置啟動(dòng)后伴箩,對(duì)應(yīng)事務(wù)分組的TC單獨(dú)為其應(yīng)用服務(wù)入愧,整體部署圖如下:
3、client的精細(xì)化控制
- 假定現(xiàn)在存在seata集群嗤谚,Guangzhou機(jī)房實(shí)例運(yùn)行在性能較高的機(jī)器上棺蛛,Shanghai集群運(yùn)行在性能較差的機(jī)器上
- 現(xiàn)存微服務(wù)架構(gòu)項(xiàng)目projectA、projectA中有微服務(wù)ServiceA巩步、ServiceB旁赊、ServiceC與ServiceD
- 其中ServiceD的流量較小,其余微服務(wù)流量較大
那么此時(shí)椅野,我們可以將ServiceD微服務(wù)引流到Shanghai集群中去终畅,將高性能的服務(wù)器讓給其余流量較大的微服務(wù)(反之亦然,若存在某一個(gè)微服務(wù)流量特別大竟闪,我們也可以單獨(dú)為此微服務(wù)開辟一個(gè)更高性能的集群离福,并將該client的virtual group指向該集群,其最終目的都是保證在流量洪峰時(shí)服務(wù)的可用)
4瘫怜、Seata的預(yù)發(fā)與生產(chǎn)隔離
- 大多數(shù)情況下术徊,預(yù)發(fā)環(huán)境與生產(chǎn)環(huán)境會(huì)使用同一套數(shù)據(jù)庫(kù)【ㄅ龋基于這個(gè)條件赠涮,預(yù)發(fā)TC集群與生產(chǎn)TC集群必須使用同一個(gè)數(shù)據(jù)庫(kù)保證全局事務(wù)的生效(即生產(chǎn)TC集群與預(yù)發(fā)TC集群使用同一個(gè)lock表子寓,并使用不同的branch_table與global_table的情況)
- 我們記生產(chǎn)使用的branch表與global表分別為:global_table與branch_table;預(yù)發(fā)為global_table_pre笋除,branch_table_pre
- 預(yù)發(fā)與生產(chǎn)共用lock_table
此時(shí)斜友,seata-server的 file.conf 配置如下
store {
mode = "db"
db {
datasource = "druid"
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata"
user = "username"
password = "password"
minConn = 5
maxConn = 100
globalTable = "global_table" ----> 預(yù)發(fā)為 "global_table_pre"
branchTable = "branch_table" ----> 預(yù)發(fā)為 "branch_table_pre"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}
seata-server的 registry.conf 配置如下(以nacos為例)
registry {
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "DEFAULT_GROUP"
namespace = "8f11aeb1-5042-461b-b88b-d47a7f7e01c0"
cluster = "pre-product" -->同理生產(chǎn)為 "product"
username = "username"
password = "password"
}
}
其部署圖如下所示:
不僅如此,你還可以將以上四個(gè)最佳實(shí)踐依據(jù)你的實(shí)際生產(chǎn)情況組合搭配使用
四垃它、api支持
此處記錄一下低級(jí)別api的使用
1. 遠(yuǎn)程調(diào)用事務(wù)上下文的傳播
遠(yuǎn)程調(diào)用前獲取當(dāng)前 XID:
String xid = RootContext.getXID();
遠(yuǎn)程調(diào)用過(guò)程把 XID 也傳遞到服務(wù)提供方鲜屏,在執(zhí)行服務(wù)提供方的業(yè)務(wù)邏輯前,把 XID 綁定到當(dāng)前應(yīng)用的運(yùn)行時(shí):
RootContext.bind(rpcXid);
2. 事務(wù)的暫停和恢復(fù)
在一個(gè)全局事務(wù)中国拇,如果需要某些業(yè)務(wù)邏輯不在全局事務(wù)的管轄范圍內(nèi)洛史,則在調(diào)用前,把 XID 解綁:
String unbindXid = RootContext.unbind();
待相關(guān)業(yè)務(wù)邏輯執(zhí)行完成酱吝,再把 XID 綁定回去也殖,即可實(shí)現(xiàn)全局事務(wù)的恢復(fù):
RootContext.bind(unbindXid);
五、可能遇到的問(wèn)題
1务热、undo_log表log_status=1的記錄是做什么用的忆嗜?
- 場(chǎng)景 : 分支事務(wù)a注冊(cè)TC后,a的本地事務(wù)提交前發(fā)生了全局事務(wù)回滾
- 后果 : 全局事務(wù)回滾成功崎岂,a資源被占用掉捆毫,產(chǎn)生了資源懸掛問(wèn)題
- 防懸掛措施: a回滾時(shí)發(fā)現(xiàn)回滾undo還未插入,則插入一條log_status=1的undo記錄冲甘,a本地事務(wù)(業(yè)務(wù)寫操作sql和對(duì)應(yīng)undo為一個(gè)本地事務(wù))提交時(shí)會(huì)因?yàn)閡ndo表唯一索引沖突而提交失敗绩卤。
2、如何保證事物的隔離性损合?
因seata一階段本地事務(wù)已提交省艳,為防止其他事務(wù)臟讀臟寫需要加強(qiáng)隔離。
- 臟讀 select語(yǔ)句加for update嫁审,代理方法增加@GlobalLock+@Transactional或@GlobalTransaction
- 臟寫 必須使用@GlobalTransaction
注:如果你查詢的業(yè)務(wù)的接口沒(méi)有GlobalTransactional 包裹跋炕,也就是這個(gè)方法上壓根沒(méi)有分布式事務(wù)的需求,這時(shí)你可以在方法上標(biāo)注@GlobalLock+@Transactional 注解律适,并且在查詢語(yǔ)句上加 for update辐烂。 如果你查詢的接口在事務(wù)鏈路上外層有GlobalTransactional注解,那么你查詢的語(yǔ)句只要加for update就行捂贿。設(shè)計(jì)這個(gè)注解的原因是在沒(méi)有這個(gè)注解之前纠修,需要查詢分布式事務(wù)讀已提交的數(shù)據(jù),但業(yè)務(wù)本身不需要分布式事務(wù)厂僧。 若使用GlobalTransactional注解就會(huì)增加一些沒(méi)用的額外的rpc開銷比如begin 返回xid扣草,提交事務(wù)等。GlobalLock簡(jiǎn)化了rpc過(guò)程,使其做到更高的性能辰妙。
3鹰祸、臟數(shù)據(jù)會(huì)滾失敗如何處理?
- 臟數(shù)據(jù)需手動(dòng)處理密浑,根據(jù)日志提示修正數(shù)據(jù)或者將對(duì)應(yīng)undo刪除(可自定義實(shí)現(xiàn)FailureHandler做郵件通知或其他)
- 關(guān)閉回滾時(shí)undo鏡像校驗(yàn)蛙婴,不推薦該方案。
注:建議事前做好隔離保證無(wú)臟數(shù)據(jù)
4尔破、使用 AT 模式需要的注意事項(xiàng)有哪些 街图?
- 必須使用代理數(shù)據(jù)源,有 3 種形式可以代理數(shù)據(jù)源:
- 依賴 seata-spring-boot-starter 時(shí)懒构,自動(dòng)代理數(shù)據(jù)源餐济,無(wú)需額外處理。
- 依賴 seata-all 時(shí)痴脾,使用 @EnableAutoDataSourceProxy (since 1.1.0) 注解颤介,注解參數(shù)可選擇 jdk 代理或者 cglib 代理。
- 依賴 seata-all 時(shí)赞赖,也可以手動(dòng)使用 DatasourceProxy 來(lái)包裝 DataSource。
- 配置 GlobalTransactionScanner冤灾,使用 seata-all 時(shí)需要手動(dòng)配置前域,使用 seata-spring-boot-starter 時(shí)無(wú)需額外處理。
- 業(yè)務(wù)表中必須包含單列主鍵韵吨,若存在復(fù)合主鍵匿垄,請(qǐng)參考問(wèn)題 13 。
- 每個(gè)業(yè)務(wù)庫(kù)中必須包含 undo_log 表归粉,若與分庫(kù)分表組件聯(lián)用椿疗,分庫(kù)不分表。
- 跨微服務(wù)鏈路的事務(wù)需要對(duì)相應(yīng) RPC 框架支持糠悼,目前 seata-all 中已經(jīng)支持:Apache Dubbo届榄、Alibaba Dubbo、sofa-RPC倔喂、Motan铝条、gRpc、httpClient席噩,對(duì)于 Spring Cloud 的支持班缰,請(qǐng)大家引用 spring-cloud-alibaba-seata。其他自研框架悼枢、異步模型埠忘、消息消費(fèi)事務(wù)模型請(qǐng)結(jié)合 API 自行支持。
- 目前AT模式支持的數(shù)據(jù)庫(kù)有:MySQL、Oracle莹妒、PostgreSQL和 TiDB名船。
- 使用注解開啟分布式事務(wù)時(shí),若默認(rèn)服務(wù) provider 端加入 consumer 端的事務(wù)动羽,provider 可不標(biāo)注注解包帚。但是,provider 同樣需要相應(yīng)的依賴和配置运吓,僅可省略注解渴邦。
- 使用注解開啟分布式事務(wù)時(shí),若要求事務(wù)回滾拘哨,必須將異常拋出到事務(wù)的發(fā)起方谋梭,被事務(wù)發(fā)起方的 @GlobalTransactional 注解感知到。provide 直接拋出異常 或 定義錯(cuò)誤碼由 consumer 判斷再拋出異常倦青。
5瓮床、AT 模式和 Spring @Transactional 注解連用時(shí)需要注意什么 ?
@Transactional 可與 DataSourceTransactionManager 和 JTATransactionManager 連用分別表示本地事務(wù)和XA分布式事務(wù)产镐,大家常用的是與本地事務(wù)結(jié)合隘庄。當(dāng)與本地事務(wù)結(jié)合時(shí),@Transactional和@GlobalTransaction連用癣亚,@Transactional 只能位于標(biāo)注在@GlobalTransaction的同一方法層次或者位于@GlobalTransaction 標(biāo)注方法的內(nèi)層丑掺。這里分布式事務(wù)的概念要大于本地事務(wù),若將 @Transactional 標(biāo)注在外層會(huì)導(dǎo)致分布式事務(wù)空提交述雾,當(dāng)@Transactional 對(duì)應(yīng)的 connection 提交時(shí)會(huì)報(bào)全局事務(wù)正在提交或者全局事務(wù)的xid不存在街州。
6、SpringCloud xid無(wú)法傳遞 玻孟?
1.首先確保你引入了spring-cloud-alibaba-seata的依賴.
2.如果xid還無(wú)法傳遞,請(qǐng)確認(rèn)你是否實(shí)現(xiàn)了WebMvcConfigurer,如果是,請(qǐng)參考com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration#addInterceptors的方法.把SeataHandlerInterceptor加入到你的攔截鏈路中.
7唆缴、使用mybatis-plus 動(dòng)態(tài)數(shù)據(jù)源組件后undolog無(wú)法刪除 ?
dynamic-datasource-spring-boot-starter 組件內(nèi)部開啟seata后會(huì)自動(dòng)使用DataSourceProxy來(lái)包裝DataSource,所以需要以下方式來(lái)保持兼容
1.如果你引入的是seata-all,請(qǐng)不要使用@EnableAutoDataSourceProxy注解.
2.如果你引入的是seata-spring-boot-starter 請(qǐng)關(guān)閉自動(dòng)代理
seata:
enable-auto-data-source-proxy: false
8黍翎、數(shù)據(jù)庫(kù)開啟自動(dòng)更新時(shí)間戳導(dǎo)致臟數(shù)據(jù)無(wú)法回滾面徽?
由于業(yè)務(wù)提交,seata記錄當(dāng)前鏡像后玩敏,數(shù)據(jù)庫(kù)又進(jìn)行了一次時(shí)間戳的更新斗忌,導(dǎo)致鏡像校驗(yàn)不通過(guò)。
**解決方案1: **關(guān)閉數(shù)據(jù)庫(kù)的時(shí)間戳自動(dòng)更新旺聚。數(shù)據(jù)的時(shí)間戳更新织阳,如修改、創(chuàng)建時(shí)間由代碼層面去維護(hù)砰粹,比如MybatisPlus就能做自動(dòng)填充唧躲。
解決方案2: update語(yǔ)句別把沒(méi)更新的字段也放入更新語(yǔ)句造挽。
9、Seata 使用注冊(cè)中心注冊(cè)的地址有什么限制弄痹?
Seata 注冊(cè)中心不能注冊(cè) 0.0.0.0 或 127.0.0.1 的地址饭入,當(dāng)自動(dòng)注冊(cè)為上述地址時(shí)可以通過(guò)啟動(dòng)參數(shù) -h 或容器環(huán)境變量SEATA_IP來(lái)指定。當(dāng)和業(yè)務(wù)服務(wù)處于不同的網(wǎng)絡(luò)時(shí)注冊(cè)地址可以指定為 NAT_IP或公網(wǎng)IP肛真,但需要保證注冊(cè)中心的健康檢查探活是通暢的谐丢。
10、seata服務(wù)自檢
首先通過(guò)讀取 client.tm.degradeCheck 是否為true,決定是否開啟自檢線程.隨后讀取degradeCheckAllowTimes和degradeCheckPeriod,確認(rèn)閾值與自檢周期. 假設(shè)degradeCheckAllowTimes=10,degradeCheckPeriod=2000 那么每2秒鐘會(huì)進(jìn)行一個(gè)begin,commit的測(cè)試,如果失敗,則記錄連續(xù)失敗數(shù),如果成功則清空連續(xù)失敗數(shù).連續(xù)錯(cuò)誤由用戶接口及自檢線程進(jìn)行累計(jì),直到連續(xù)失敗次數(shù)達(dá)到用戶的閾值,則關(guān)閉Seata分布式事務(wù),避免用戶自身業(yè)務(wù)長(zhǎng)時(shí)間不可用. 反之,假如當(dāng)前分布式事務(wù)關(guān)閉,那么自檢線程繼續(xù)按照2秒一次的自檢,直到連續(xù)成功數(shù)達(dá)到用戶設(shè)置的閾值,那么Seata分布式事務(wù)將恢復(fù)使用
11蚓让、設(shè)置mysql的連接參數(shù)rewriteBatchedStatements=true
在store.mode=db乾忱,由于seata是通過(guò)jdbc的executeBatch來(lái)批量插入全局鎖的,根據(jù)MySQL官網(wǎng)的說(shuō)明历极,連接參數(shù)中的rewriteBatchedStatements為true時(shí)窄瘟,在執(zhí)行executeBatch,并且操作類型為insert時(shí)趟卸,jdbc驅(qū)動(dòng)會(huì)把對(duì)應(yīng)的SQL優(yōu)化成insert into () values (), ()
的形式來(lái)提升批量插入的性能蹄葱。 根據(jù)實(shí)際的測(cè)試,該參數(shù)設(shè)置為true后锄列,對(duì)應(yīng)的批量插入性能為原來(lái)的10倍多图云,因此在數(shù)據(jù)源為MySQL時(shí),建議把該參數(shù)設(shè)置為true邻邮。
六琼稻、參考資料
2饶囚、seata參數(shù)配置
4鸠补、seata事務(wù)分組的例子
5萝风、可支持的SQL限制