成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

@Transactional 竟也能解決分布式事務?

開發 前端
在Sharding-JDBC中明明只是簡單的使用@Transactional這個本地事務注解,為什么在跨庫插入數據時候卻能夠同時回滾?

前天朋友咨詢過我一個問題,大致內容如下:

圖片

這位讀者什么意思呢?簡單的總結下:在Sharding-JDBC中明明只是簡單的使用@Transactional這個本地事務注解,為什么在跨庫插入數據時候卻能夠同時回滾?

我們知道單數據節點的情況下保持事務是非常簡單的,只需要使用本地事務即可輕松解決,比如常用的注解:@Transactional。

但是在分庫后將會存在跨庫的事務,此時本地事務還能保證事務嗎?

這篇文章就以球友的提問來聊一下Sharding-JDBC中的本地事務。

本地事務

Sharding-JDBC中的本地事務可能會讓大家有一個誤解,還是以商品表為例:將商品表根據商品ID進行水平分庫,分為兩個庫,如下:

圖片

分庫的配置這里就不貼了,詳情看源碼。

此時向其中批量插入數據,偽代碼如下:

@Transactional
public int insertBatch(){
for(int i=0;i<10;i++){
insert(product);
.......
}
}

上述案例中使用了@Transactional?開啟了本地事務,但是內部在插入數據時,Sharding-JDB會根據product_id?這個分片鍵進行分庫,那么這個業務方法肯定是跨了DB1、DB2?這兩個庫,@Transactional這個注解能解決嗎?

假象:手動在內部模擬拋出異常,還真的是都rollback了。

此時很多人都迷糊了,Sharding-JDBC中的本地事務真的是可以保證分布式事務?

真實結論:Sharding-JDBC中的本地事務無法保證分布式事。

Sharding-JDBC中的本地事務在以下兩種情況是完全支持的:

  • 支持非跨庫事務,比如僅分表、在單庫中操作。
  • 支持因邏輯異常導致的跨庫事務,比如上述的操作,跨兩個庫插入數據,插入完成后拋出異常。

本地事務不支持的情況:

  • 不支持因網絡、硬件異常導致的跨庫事務;例如:同一事務中,跨兩個庫更新,更新完畢后、未提交之前,第一個庫宕機,則只有第二個庫數據提交。

對于因網絡、硬件異常導致的跨庫事務無法支持很好理解,在分布式事務中無論是兩階段還是三階段提交都是直接或者間接滿足以下兩個條件:

  • 有一個事務協調者
  • 事務日志記錄

本地事務并未滿足上述條件,自然是無法支持

為什么邏輯異常導致的跨庫事務能夠支持?

Spring的本地事務大家都很了解,也經常用,并不支持的跨庫事務,那么為什么Sharding-JDBC中卻能支持呢?

想要了解其中的貓膩必然需要從Sharding-JDBC的源碼入手,下圖是在Sharding-JDBC一條SQL處理的流程:

圖片

Sharding-JDBC中的一條SQL會經過改寫,拆分成不同數據源的SQL,比如一條select語句,會按照其中分片鍵拆分成對應數據源的SQL,然后在不同數據源中的執行,最終會提交或者回滾。

想要解釋上述的問題,只需要看ShardingConnection,這是Sharding-JDBC自定義實現的,繼承關系如下圖:

圖片

可以看到ShardingConnection?繼承了java.sql.Connection,這個類就不必多解釋了,在學習JDBC的時候應該都有所接觸,直接和數據庫打交道的一個類。

想要知道為什么支持跨庫事務的回滾,肯定要找到其中的rollback方法,如下:

@Override
public void rollback() throws SQLException {
//① 本地事務
f (TransactionType.LOCAL == transactionType) {
super.rollback();
} else {
//② 非本地事務
shardingTransactionManager.rollback();
}
}

rollback?的方法中區分了本地事務和分布式事務,如果是本地事務將調用父類的rollback方法,如下:

//父類:AbstractConnectionAdapter#rollback

@Override
public void rollback() throws SQLException {
//cachedConnections中存儲了數據源,這里是ds1/ds2
forceExecuteTemplate.execute(cachedConnections.values(), Connection::rollback);
}

這里是調用ForceExecuteTemplate#execute()?方法執行,其實內部就是遍歷數據源去執行對應的rollback方法,如下:

public void execute(final Collection<T> targets, final ForceExecuteCallback<T> callback) throws SQLException {
Collection<SQLException> exceptions = new LinkedList<>();
for (T each : targets) {
try {
callback.execute(each);
} catch (final SQLException ex) {
exceptions.add(ex);
}
}
throwSQLExceptionIfNecessary(exceptions);
}

看到這里已經很明了了,rollback? 在各個數據源中回滾且未記錄任何事務日志,因此在非硬件、網絡的情況下都是可以正常回滾的,一旦因為網絡、硬件故障,可能導致某個數據源rollback失敗,這樣即使程序恢復了正常,也無undo日志繼續進行rollback,因此這里就造成了數據不一致了。

總結

僅僅依靠Spring自帶的本地事務(@Transactional)是無法保證跨庫的分布式事務,不要被Sharding-JDBC的假象迷惑了。

當然Sharding-JDBC對于跨庫事務也是有一定的支持,大致分成三類:

  • 強一致性的XA協議事務
  • 基于Base的柔性事務
  • 通過SPI機制自定義擴展的分布式事務解決方案

本文只是拋磚引玉簡單的介紹下分庫分表后的事務處理,后文會針對以上三類方案詳細介紹一下。

責任編輯:武曉燕 來源: 碼猿技術專欄
相關推薦

2022-03-24 07:51:27

seata分布式事務Java

2025-04-29 04:00:00

分布式事務事務消息

2022-06-27 08:21:05

Seata分布式事務微服務

2022-06-14 10:47:00

分布式事務數據

2022-06-21 08:27:22

Seata分布式事務

2017-07-26 15:08:05

大數據分布式事務

2025-04-30 10:44:02

2024-10-09 14:14:07

2023-09-14 15:44:46

分布式事務數據存儲

2020-05-28 09:35:05

分布式事務方案

2019-10-10 09:16:34

Zookeeper架構分布式

2009-06-19 15:28:31

JDBC分布式事務

2009-09-18 15:10:13

分布式事務LINQ TO SQL

2021-09-29 09:07:37

分布式架構系統

2025-04-28 00:44:04

2020-12-09 09:14:57

SpringCloudSeata 分布式

2019-06-26 09:41:44

分布式事務微服務

2019-01-11 18:22:07

阿里巴巴技術開源

2010-07-21 13:53:41

SQL Server分

2025-05-15 08:05:00

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品不卡视频 | 日本一区二区三区在线观看 | 久草新视频| 国产精品久久亚洲7777 | 亚洲福利av| 黄色网络在线观看 | 91精品综合久久久久久五月天 | 欧美a在线观看 | 成人av大全 | 精品亚洲国产成av人片传媒 | 久久福利电影 | 精品日韩一区二区 | 日韩在线免费视频 | 日韩精品a在线观看图片 | 色橹橹欧美在线观看视频高清 | 一区二区三区精品视频 | 国内精品免费久久久久软件老师 | 免费高清av | 黄色一级在线播放 | 亚洲 欧美 日韩 在线 | 亚洲日韩中文字幕一区 | 两性午夜视频 | 国产日韩一区二区三区 | www久久国产 | 亚洲www啪成人一区二区麻豆 | 国产福利在线 | 九九热免费观看 | 久久久久亚洲精品 | 日韩二| 欧美精品一区二区三区在线播放 | 亚洲欧美综合精品另类天天更新 | 欧美在线资源 | 欧美一区在线看 | 成人黄色av网址 | 欧美日韩视频 | 在线国产一区 | 国产成人精品免费视频大全最热 | 亚洲欧美激情精品一区二区 | 精品欧美一区二区三区久久久 | 精品网站999www | 亚洲欧美日韩精品久久亚洲区 |