MySQL核心月報2015.01-MySQL·優化改進·複製效能改進過程

db匠發表於2016-05-23

前言

與oracle 不同,mysql 的主庫與備庫的同步是通過 binlog 實現的,而redo日誌只做為mysql 例項的crash recovery使用。mysql在4.x 的時候放棄redo 的同步策略而引入 binlog的同步,一個重要原因是為了相容其它非事務儲存引擎,否則主備同步是沒有辦法進行的。

redo 日誌同步屬於物理同步方法,簡單直接,將修改的物理部分傳送到備庫執行,主備共用一致的 LSN,只要保證 LSN 相同即可,同一時刻,只能主庫或備庫一方接受寫請求; binlog的同步方法屬於邏輯複製,分為statement 或 row 模式,其中statement記錄的是SQL語句,Row 模式記錄的是修改之前的記錄與修改之後的記錄,即前映象與後映象;備庫通過binlog dump 協議拉取binlog,然後在備庫執行。如果拉取的binlog是SQL語句,備庫會走和主庫相同的邏輯,如果是row 格式,則會呼叫儲存引擎來執行相應的修改。

本文簡單說明5.5到5.7的主備複製效能改進過程。

replication improvement (from 5.5 to 5.7)

(1) 5.5 中,binlog的同步是由兩個執行緒執行的

io_thread: 根據binlog dump協議從主庫拉取binlog, 並將binlog轉存到本地的relaylog;

sql_thread: 讀取relaylog,根據位點的先後順序執行binlog event,進而將主庫的修改同步到備庫,達到主備一致的效果; 由於在主庫的更新是由多個客戶端執行的,所以當壓力達到一定的程度時,備庫單執行緒執行主庫的binlog跟不上主庫執行的速度,進而會產生延遲造成備庫不可用,這也是分庫的原因之一,其SQL執行緒的執行堆疊如下:


(2) 5.6 中,引入了多執行緒模式,在多執行緒模式下,其執行緒結構如下

io_thread: 同5.5

Coordinator_thread: 負責讀取 relay log,將讀取的binlog event以事務為單位分發到各個 worker thread 進行執行,並在必要時執行binlog event(Description_format_log_event, Rotate_log_event 等)。

worker_thread: 執行分配到的binlog event,各個執行緒之間互不影響;

多執行緒原理

sql_thread 的分發原理是依據當前事務所操作的資料庫名稱來進行分發,如果事務是跨資料庫行為的,則需要等待已分配的該資料庫的事務全部執行完畢,才會繼續分發,其分配行為的偽碼可以簡單的描述如下:


需要注意的細節

    • 記憶體的分配與釋放。relay thread 每讀取一個log_event, 則需要 malloc 一定的記憶體,在work執行緒執行完後,則需要free掉;
    • 資料庫名 與 worker 執行緒的繫結資訊在一個hash表中進行維護,hash表以entry為單位,entry中記錄當前entry所代表的資料庫名,有多少個事務相關的已被分發,執行這些事務的worker thread等資訊;
    • 維護一個繫結資訊的array , 在分發事務的時候,更新繫結資訊,增加相應 entry->usage, 在執行完一個事務的時候,則需要減少相應的entry->usage;
    • slave worker 資訊的維護,即每個 worker thread執行了哪些事務,執行到的位點是在哪,延遲是如何計算的,如果執行出錯,mts_recovery_group 又是如何恢復的;
    • 分配執行緒是以資料庫名進行分發的,當一個例項中只有一個資料庫的時候,不會對效能有提高,相反,由於增加額外的操作,效能還會有一點回退;
    • 臨時表的處理,臨時表是和entry繫結在一起的,在執行的時候將entry的臨時表掛在執行執行緒thd下面,但沒有固化,如果在臨時表操作期間,備庫crash,則重啟後備庫會有錯誤;

總體上說,5.6 的並行複製打破了5.5 單執行緒的複製的行為,只是在單庫下用處不大,並且5.6的並行複製的改動引入了一些重量級的bug

(3) 5.7中,並行複製的實現新增了另外一種並行的方式,即主庫在 ordered_commit中的第二階段的時候,將同一批commit的 binlog 打上一個相同的seqno標籤,同一時間戳的事務在備庫是可以同時執行的,因此大大簡化了並行複製的邏輯,並打破了相同 DB 不能並行執行的限制。備庫在執行時,具有同一seqno的事務在備庫可以並行的執行,互不干擾,也不需要繫結資訊,後一批seqno的事務需要等待前一批相同seqno的事務執行完後才可以執行。

詳細實現可參考:http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6256 。

reference:http://geek.rohitkalhans.com/2013/09/enhancedMTS-deepdive.html


相關文章