在開發中,為了降低單點壓力,通常會根據業務情況進行分表分庫,將表分布在不同的庫中(庫可能分布在不同的機器上)。在這種場景下,事務的提交會變得相對複雜,因為多個節點(庫)的存在,可能存在部分節點提交失敗的情況,即事務的acid特性需要在各個不同的資料庫例項中保證。比如更新db1庫的a表時,必須同步更新db2庫的b表,兩個更新形成乙個事務,要麼都成功,要麼都失敗。
那麼我們如何利用mysql實現分布式資料庫的事務呢?
mysql 為我們提供了分布式事務解決方案( 這是mysql5.7的文件)
這裡先宣告兩個概念:
mysql在執行分布式事務(外部xa)的時候,mysql伺服器相當於xa事務資源管理器,與mysql鏈結的客戶端相當於事務管理器。
分布式事務通常採用2pc協議,全稱two phase commitment protocol。該協議主要為了解決在分布式資料庫場景下,所有節點間資料一致性的問題。分布式事務通過2pc協議將提交分成兩個階段:
prepare;
commit/rollback
階段一為準備(prepare)階段。即所有的參與者準備執行事務並鎖住需要的資源。參與者ready時,向transaction manager報告已準備就緒。
階段二為提交階段(commit)。當transaction manager確認所有參與者都ready後,向所有參與者傳送commit命令。
如下圖所示:
因為xa 事務是基於兩階段提交協議的,所以需要有乙個事務協調者(transaction manager)來保證所有的事務參與者都完成了準備工作(第一階段)。如果事務協調者(transaction manager)收到所有參與者都準備好的訊息,就會通知所有的事務都可以提交了(第二階段)。mysql 在這個xa事務中扮演的是參與者的角色,而不是事務協調者(transaction manager)。
外部xa用於跨多mysql例項的分布式事務,需要應用層作為協調者,通俗的說就是比如我們在php中寫**,那麼php書寫的邏輯就是協調者。應用層負責決定提交還是回滾,崩潰時的懸掛事務。mysql資料庫外部xa可以用在分布式資料庫**層,實現對mysql資料庫的分布式事務支援,例如開源的**工具:網易的ddb,**的tddl等等。
內部xa事務用於同一例項下跨多引擎事務,由binlog作為協調者,比如在乙個儲存引擎提交時,需要將提交資訊寫入二進位制日誌,這就是乙個分布式內部xa事務,只不過二進位制日誌的參與者是mysql本身。binlog作為內部xa的協調者,在binlog**現的內部xid,在crash recover時,由binlog負責提交。(這是因為,binlog不進行prepare,只進行commit,因此在binlog**現的內部xid,一定能夠保證其在底層各儲存引擎中已經完成prepare)。
mysql xa事務基本語法
xa xid [join|resume] 啟動xid事務 (xid 必須是乙個唯一值; 不支援[join|resume]子句)
xa end xid [suspend [for migrate]] 結束xid事務 ( 不支援[suspend [for migrate]] 子句)
xa prepare xid 準備、預提交xid事務
xa commit xid [one phase] 提交xid事務
xa rollback xid 回滾xid事務
xa recover 檢視處於prepare 階段的所有事務
1、首先要確保mysql開啟xa事務支援
show variables like '%xa%'
如果innodb_support_xa的值是on就說明mysql已經開啟對xa事務的支援了。
如果不是就執行:
set innodb_support_xa = on
開啟2、**如下:
<?php
$dbtest1 = new mysqli("172.20.101.17","public","public","dbtest1")or die("dbtest1 連線失敗");
$dbtest2 = new mysqli("172.20.101.18","public","public","dbtest2")or die("dbtest2 連線失敗");
//為xa事務指定乙個id,xid 必須是乙個唯一值。
$xid = uniqid("");
//兩個庫指定同乙個事務id,表明這兩個庫的操作處於同一事務中
$dbtest1->query("xa start '$xid'");//準備事務1
$dbtest2->query("xa start '$xid'");//準備事務2
try
//$dbtest2
$return = $dbtest2->query("update memberpoints set point=point+10 where memberid=1") ;
if($return == false)
//階段1:$dbtest1提交準備就緒
$dbtest1->query("xa end '$xid'");
$dbtest1->query("xa prepare '$xid'");
//階段1:$dbtest2提交準備就緒
$dbtest2->query("xa end '$xid'");
$dbtest2->query("xa prepare '$xid'");
//階段2:提交兩個庫
$dbtest1->query("xa commit '$xid'");
$dbtest2->query("xa commit '$xid'");
} catch (exception $e)
$dbtest1->close();
$dbtest2->close();
?>
xa的效能很低。乙個資料庫的事務和多個資料庫間的xa事務效能對比可發現,效能差10倍左右。因此要盡量避免xa事務,例如可以將資料寫入本地,用高效能的訊息系統分發資料。或使用資料庫複製等技術。只有在這些都無法實現,且效能不是瓶頸時才應該使用xa。 mysql分布式事務
儲引擎實現事務的通用方式是基於 redo log 和 undo log。簡單來說,redo log 記錄事務修改後的資料,undo log 記錄事務前的原始資料。所以當乙個事務執行時實際發生過程簡化描述如下 先記錄 undo redo log,確保日誌刷到磁碟上持久儲存。更新資料記錄,快取操作並非同...
MySQL分布式事務
mysql5.0.3開始支援分布式事務,只支援innodb引擎。1.分布式事務原理 使用分布式事務的應用程式涉及乙個或多個資源管理器和乙個事務管理器。資源管理器 rm 用於提供通向事務資源的途徑,資料庫伺服器是一種資源管理器。該管理器必須可以提交或回滾由rm管理的事務。事務管理器 tm 用於協調作為...
Mysql分布式事務
關於mysql分布式事務介紹,可參考 分為兩個階段 準備和執行階段。有兩個角色 事務的管理者 tm 和事務執行者 rm,mysql server xa start 事務啟動標識,使事務處於active狀態 xa end 事務結束標識,使事務處於idle狀態 當事務處於idle狀態,可 xa prep...