您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“MySQL 5.7的分布式事務(wù)支持舉例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“MySQL 5.7的分布式事務(wù)支持舉例分析”吧!
分布式事務(wù)通常采用2PC協(xié)議,全稱Two Phase Commitment Protocol。該協(xié)議主要為了解決在分布式數(shù)據(jù)庫場景下,所有節(jié)點間數(shù)據(jù)一致性的問題。在分布式事務(wù)環(huán)境下,事務(wù)的提交會變得相對比較復雜,因為多個節(jié)點的存在,可能存在部分節(jié)點提交失敗的情況,即事務(wù)的ACID特性需要在各個數(shù)據(jù)庫實例中保證??偠灾?,在分布式提交時,只要發(fā)生一個節(jié)點提交失敗,則所有的節(jié)點都不能提交,只有當所有節(jié)點都能提交時,整個分布式事務(wù)才允許被提交。
分布式事務(wù)通過2PC協(xié)議將提交分成兩個階段
prepare;
commit/rollback
第一階段的prepare只是用來詢問每個節(jié)點事務(wù)是否能提交,只有當?shù)玫剿泄?jié)點的“許可”的情況下,第二階段的commit才能進行,否則就rollback。需要注意的是:prepare成功的事務(wù),則必須全部提交。
一直以來,MySQL數(shù)據(jù)庫是支持分布式事務(wù)的,但是只能說是有限的支持,具體表現(xiàn)在:
已經(jīng)prepare的事務(wù),在客戶端退出或者服務(wù)宕機的時候,2PC的事務(wù)會被回滾
在服務(wù)器故障重啟提交后,相應(yīng)的Binlog被丟失
上述問題存在于MySQL數(shù)據(jù)庫長達數(shù)十年的時間,直到MySQL-5.7.7版本,官方才修復了該問題。雖然InnoSQL早已在5.5版本修復,但是對比官方的修復方案,我們真的做的沒有那么的優(yōu)雅。下面將會詳細介紹下該問題的具體表現(xiàn)和官方修復方法,這里分別采用官方MySQL-5.6.27版本(未修復)和MySQL-5.7.9版本(已修復)進行驗證。
先來看下存在的問題,我們先創(chuàng)建一個表如下:
create table t( id int auto_increment primary key, a int )engine=innodb;
對于上述表,通過如下操作進行數(shù)據(jù)插入:
mysql> XA START 'mysql56'; mysql> INSERT INTO t VALUES(1,1); mysql> XA END 'mysql56'; mysql> XA PREPARE 'mysql56'
通過上面的操作,用戶創(chuàng)建了一個分布式事務(wù),并且prepare沒有返回錯誤,說明該分布式事務(wù)可以被提交。通過命令XA RECOVER查看顯示如下結(jié)果:
mysql> XA RECOVER; +----------+--------------+--------------+---------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+---------+ | 1 | 7 | 0 | mysql56 | +----------+--------------+--------------+---------+
若這時候用戶退出客戶端后重連,通過命令xa recover會發(fā)現(xiàn)剛才創(chuàng)建的2PC事務(wù)不見了。即prepare成功的事務(wù)丟失了,不符合2PC協(xié)議規(guī)范!??!
產(chǎn)生上述問題的主要原因在于:MySQL-5.6版本在客戶端退出的時候,自動把已經(jīng)prepare的事務(wù)回滾了,那么MySQL為什么要這樣做?這主要取決于MySQL的內(nèi)部實現(xiàn),MySQL-5.7以前的版本,對于prepare的事務(wù),MySQL是不會記錄binlog的(官方說是減少fsync,起到了優(yōu)化的作用)。只有當分布式事務(wù)提交的時候才會把前面的操作寫入binlog信息,所以對于binlog來說,分布式事務(wù)與普通的事務(wù)沒有區(qū)別,而prepare以前的操作信息都保存在連接的IO_CACHE中,如果這個時候客戶端退出了,以前的binlog信息都會被丟失,再次重連后允許提交的話,會造成Binlog丟失,從而造成主從數(shù)據(jù)的不一致,所以官方在客戶端退出的時候直接把已經(jīng)prepare的事務(wù)都回滾了!
官方的做法,貌似干得很漂亮,犧牲了一點標準化的東西,至少保證了主從數(shù)據(jù)的一致性。但其實不然,若用戶已經(jīng)prepare后在客戶端退出之前,MySQL發(fā)生了宕機,這個時候又會怎樣?
MySQL在某個分布式事務(wù)prepare成功后宕機,宕機前操作該事務(wù)的連接并沒有斷開,這個時候已經(jīng)prepare的事務(wù)并不會被回滾,所以在MySQL重新啟動后,引擎層通過recover機制能恢復該事務(wù)。當然該事務(wù)的Binlog已經(jīng)在宕機過程中被丟失,這個時候,如果去提交,則會造成主從數(shù)據(jù)的不一致,即提交沒有記錄Binlog,從上丟失該條數(shù)據(jù)。所以對于這種情況,官方一般建議直接回滾已經(jīng)prepare的事務(wù)。
以上是MySQL-5.7以前版本MySQL在分布式事務(wù)上的各種問題,那么MySQL-5.7版本官方做了哪些改進?這個可以從官方的WL#6860描述上得到一些信息,我們還是本著沒有實踐就沒有發(fā)言權(quán)的態(tài)度,從具體的操作上來分析下MySQL-5.7的改進方法:
還是以上面同樣的表結(jié)構(gòu)進行同樣的操作如下:
mysql> XA START 'mysql57'; mysql> INSERT INTO t VALUES(1,1); mysql> XA END 'mysql57'; mysql> XA PREPARE 'mysql57'通過上面的操作,明顯發(fā)現(xiàn)在prepare以后,從XA START到XA PREPARE之間的操作都被記錄到了Master的Binlog中,然后通過復制關(guān)系傳到了Slave上。也就是說MySQL-5.7開始,MySQL對于分布式事務(wù),在prepare的時候就完成了寫B(tài)inlog的操作,通過新增一種叫
當然僅靠這一點是不夠的,因為我們知道Slave通過SQL thread來回放Relay log信息,由于prepare的事務(wù)能阻塞整個session,而回放的SQL thread只有一個(不考慮并行回放),那么SQL thread會不會因為被分布式事務(wù)的prepare階段所阻塞,從而造成整個SQL thread回放出現(xiàn)問題?這也正是官方要解決的第二個問題:怎么樣能使SQL thread在回放到分布式事務(wù)的prepare階段時,不阻塞后面event的回放?其實這個實現(xiàn)也很簡單(在xa.cc::applier_reset_xa_trans),只要在SQL thread回放到prepare的時候,進行類似于客戶端斷開連接的處理即可(把相關(guān)cache與SQL thread的連接句柄脫離)。最后在Slave服務(wù)器上,用戶通過命令XA RECOVER可以查到如下信息:
mysql> XA RECOVER; +----------+--------------+--------------+---------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+---------+ | 1 | 7 | 0 | mysql57 | +----------+--------------+--------------+---------+
至于上面的事務(wù)什么時候提交,一般等到Master上進行XA COMMIT ‘mysql57’后,slave上也同時會被提交。
到此,相信大家對“MySQL 5.7的分布式事務(wù)支持舉例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。