MySQL 復制對事務的處理

jopen 10年前發布 | 11K 次閱讀 MySQL 數據庫服務器

由于職業成了專職的mysql的dba,沒有原先oracle那么又大又全面的文檔,很多東西只能看著源代碼一點一點理解,最近對復制這個dba接觸較多的特性做了一些研究,這次說的是復制實現中對事務的處理。

由于線上主流版本是5.5.3x,所以這次我主要研究的也是這個批次的版本,對于新增了gtid的5.6,并行復制的5.7以后再作研究。

眾所周知,mysql的最原始實現myisam是不支持事務的,在innodb出現之前,復制的處理很簡單,任何執行的語句全部發送給slave就可以了,沒有事務那么多事情,但是從innodb開始,mysql的事務引擎越來越強,mysql最重要的復制特性也就需要對事務的支持,但以現在的目光來看,直到gtid實現之前,只能說是在無事務的實現上套了一個事務的殼子,下面要介紹的,就是這個殼子。

首先從mysql的處理線程開始說。

mysql對于所有客戶端的連接,都有一個服務端的處理線程對應,這個線程的實現是在sql_class.h里面的THD類,復制的一部分最基礎的數據結構及方法都在這個類里面。

復制事務實現最重要的結構之一,event緩存會在受到任何觸發event產生的動作之后,調用初始化函數生成該線程獨有的復制event緩存,一般而言,當線程所屬會話首次發起事務的時候,這個緩存就會被創建,可以參見THD類的

binlog_start_trans_and_stmt方法。如果是row格式的復制,在之后還會初始化table_map。

如果一切正常,當事務中執行事務語句(DML)的時候,所以這些語句形成的event都會被記錄到緩存里面,等到commit事務以后,這個緩存的數據會立即被刷入磁盤上的binlog文件里面,之后通過slave請求發送到slave,在slave重復執行。

順便提一下,mysql的binlog里面的事務都是相互獨立按順序排列的。

現在開始假設意外的發生。

正常意外一:事務執行中rollback了。

如果在一個事務中,所有執行的語句都是在innodb表上執行(對于多個事務引擎如tokudb等并用尚未測試),直接執行rollback,會導致mysql直接清除緩存,不會寫入任何event記錄到binlog。

正常意外二:事務執行中使用了非事務表(myisam),然后rollback了。

在一個事務中,即有事務表,也有非事務表,如果正常執行,則沒有任何問題,當如果在非事務表上的修改執行了,復制設置為statement的時候,binlog會把所有執行的event全部記錄下來寫入日志,包括事務與非事務語句,然后在最后面加上rollback。如果復制格式設置為row,那么所有事務表相關的數據都會被清理掉,而非事務表上的數據會被標記為已提交事務寫入binlog。

正常意外三:事務執行順序如下:事務語句1-》非事務語句2-》save point -》事務語句3 -》 rollback to savepoint -》 事務語句4 -》提交

對于上面的情況,statement情況下,所有執行的語句包括savepoint與rollback都會按順序被記錄到binlog。row情況下,非事務語句與事務語句是分別記錄到binlog中,非事務執行event會全部被記錄,事務執行event會連帶savepoint與rollback都記錄下來。

正常意外四:事務執行順序如下:事務語句1-》savepoint-》非事務語句2-》事務語句3-》rollback to savepoint-》事務語句4 -》 commit

同上。

異常意外一:master正常提交了,但是在slave執行失敗了。

master執行完成,提交之后,slave接收到relay然后執行,執行期間由于意外原因失敗了。這個時候,statement格式下,mysql會重新回到事務begin處重新執行,如果再次失敗的話就會報錯。row模式下情況類似,區別在于,如果是包含非事務表執行的事務,非事務表上的event不會被重新執行。

來自:http://my.oschina.net/llzx373/blog/282768

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!