1. 程式人生 > >Mysql主從同步-概念和原理介紹

Mysql主從同步-概念和原理介紹

Mysql主從同步-概念和原理介紹

  1. Mysql複製概念
    Mysql內建的複製功能是構建大型高效能應用程式的基礎, 將Mysql資料分佈到多個系統上,這種分佈機制是通過將Mysql某一臺主機資料複製到其它主機(slaves)上,並重新執行一遍來實現的。複製過程中一個伺服器充當主伺服器,而一個或多個其它伺服器充當從伺服器。主伺服器將更新寫入二進位制日誌檔案,並維護檔案的一個索引以跟蹤日誌迴圈。這些日誌可以記錄傳送到從伺服器的更新。當一個從伺服器連線主伺服器時,它通知主伺服器從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,然後封鎖並等待主伺服器通知新的更新。

1.1. Mysql支援哪些複製

  • 基於語句的複製: 在主伺服器執行SQL語句,在從伺服器執行同樣語句。MySQL預設採用基於語句的複製,效率較高。一旦發現沒法精確複製時, 會自動選基於行的複製。
  • 基於行的複製: 把改變的內容複製過去,而不是把命令在從伺服器上執行一遍. 從mysql5.0開始支援
  • 混合型別的複製: 預設採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。

1.2. Mysql複製解決的問題

  • 資料分佈 (Data distribution )
  • 負載平衡(load balancing)
  • 據備份(Backups) ,保證資料安全
  • 高可用性和容錯行(High availability and failover)
  • 實現讀寫分離,緩解資料庫壓力
    1. Mysql主從複製原理
      master伺服器將資料的改變都記錄到二進位制binlog日誌中,只要master上的資料發生改變,則將其改變寫入二進位制日誌;salve伺服器會在一定時間間隔內對master二進位制日誌進行探測其是否發生改變,如果發生改變,則開始一個I/O Thread請求master二進位制事件,同時主節點為每個I/O執行緒啟動一個dump執行緒,用於向其傳送二進位制事件,並儲存至從節點本地的中繼日誌中,從節點將啟動SQL執行緒從中繼日誌中讀取二進位制日誌,在本地重放,使得其資料和主節點的保持一致,最後I/O Thread和SQL Thread將進入睡眠狀態,等待下一次被喚醒。

2.1. 需要理解:

  • 從庫會生成兩個執行緒,一個I/O執行緒,一個SQL執行緒;
  • I/O執行緒會去請求主庫的binlog,並將得到的binlog寫到本地的relay-log(中繼日誌)檔案中;
  • 主庫會生成一個log dump執行緒,用來給從庫I/O執行緒傳binlog;
  • SQL執行緒,會讀取relay log檔案中的日誌,並解析成sql語句逐一執行;

2.2. 這裡注意幾點:

  • master將操作語句記錄到binlog日誌中,然後授予slave遠端連線的許可權(master要開啟binlog二進位制日誌功能;通常為了資料安全考慮,slave也開啟binlog);
  • slave開啟兩個執行緒:IO執行緒和SQL執行緒。其中:IO執行緒負責讀取master的binlog內容到中繼日誌relay log裡;SQL執行緒負責從relay log日誌裡讀出binlog內容,並更新到slave的資料庫裡,這樣就能保證slave資料和master資料保持一致了;
  • mysql複製至少需要兩個Mysql的服務,當然Mysql服務可以分佈在不同的伺服器上,也可以在一臺伺服器上啟動多個服務;
  • mysql複製最好確保master和slave伺服器上的Mysql版本相同(如果不能滿足版本一致,那麼要保證master主節點的版本低於slave從節點的版本);
  • master和slave兩節點間時間需同步;
    2.3. Mysql複製流程圖
    如上圖所示:
    Mysql主從同步-概念和原理介紹

  • Mysql複製過程的第一部分就是master記錄二進位制日誌。在每個事務更新資料完成之前,master在二日誌記錄這些改變。MySQL將事務序列的寫入二進位制日誌,即使事務中的 語句都是交叉執行的。在事件寫入二進位制日誌完成後,master通知儲存引擎提交事務;
  • 第二部分就是slave將master的binary log拷貝到它自己的中繼日誌。首先,slave開始一個工作執行緒(I/O執行緒)。I/O執行緒在master上開啟一個普通的連線,然後開始binlog dump process。Binlog dump process從master的二進位制日誌中讀取事件,如果已經跟上master,它會睡眠並等待master產生新的事件。I/O執行緒將這些事件寫入中繼日誌;
  • SQL slave thread(SQL從執行緒)處理該過程的最後一步。SQL執行緒從中繼日誌讀取事件,並重放其中的事件而更新slave的資料,使其與master中的資料一致。只要該執行緒與 I/O執行緒保持一致,中繼日誌通常會位於OS的快取中,所以中繼日誌的開銷很小;
  • 此外,在master中也有一個工作執行緒:和其它MySQL的連線一樣,slave在master中開啟一個連線也會使得master開始一個執行緒。複製過程有一個很重要的限制, 即複製在slave上是序列化的,也就是說master上的並行更新操作不能在slave上並行操作。

2.4. Mysql複製方案
主從複製: 主庫授權從庫遠端連線,讀取binlog日誌並更新到本地資料庫的過程;主庫寫資料後,從庫會自動同步過來(從庫跟著主庫變);
主主複製: 主從相互授權連線,讀取對方binlog日誌並更新到本地資料庫的過程;只要對方資料改變,自己就跟著改變;
2.5. Mysql主從複製優點
在從伺服器可以執行查詢工作(即我們常說的讀功能),降低主伺服器壓力;(主庫寫,從庫讀,降壓)
在從主伺服器進行備份,避免備份期間影響主伺服器服務;(確保資料安全)
當主伺服器出現問題時,可以切換到從伺服器。(提升效能)
2.6. Mysql主從複製工作流程關鍵細節
1) MySQL支援單向、非同步複製,複製過程中一個伺服器充當主伺服器,而一個或多個其它伺服器充當從伺服器。MySQL複製基於主伺服器在二進位制日誌中跟蹤所有對資料庫的更改(更新、刪除等等)。因此,要進行復制,必須在主伺服器上啟用二進位制日誌。每個從伺服器從主伺服器接收主伺服器上已經記錄到其二進位制日誌的儲存的更新。當一個從伺服器連線主伺服器時,它通知主伺服器定位到從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,並在本機上執行相同的更新。然後封鎖並等待主伺服器通知新的更新。從伺服器執行備份不會干擾主伺服器,在備份過程中主伺服器可以繼續處理更新。
2) MySQL使用3個執行緒來執行復制功能,其中兩個執行緒(Sql執行緒和IO執行緒)在從伺服器,另外一個執行緒(IO執行緒)在主伺服器。當發出START SLAVE時,從伺服器建立一個I/O執行緒,以連線主伺服器並讓它傳送記錄在其二進位制日誌中的語句。主伺服器建立一個執行緒將二進位制日誌中的內容傳送到從伺服器。該執行緒可以即為主伺服器上SHOW PROCESSLIST的輸出中的Binlog Dump執行緒。從伺服器I/O執行緒讀取主伺服器Binlog Dump執行緒傳送的內容並將該資料拷貝到從伺服器資料目錄中的本地檔案中,即中繼日誌。第3個執行緒是SQL執行緒,由從伺服器建立,用於讀取中繼日誌並執行日誌中包含的更新。在從伺服器上,讀取和執行更新語句被分成兩個獨立的任務。當從伺服器啟動時,其I/O執行緒可以很快地從主伺服器索取所有二進位制日誌內容,即使SQL執行緒執行更新的遠遠滯後。

  1. Mysql主從複製注意事項小結
    3.1. Mysql主從資料完成同步的過程
    1) 在Slave 伺服器上執行sart slave命令開啟主從複製開關,開始進行主從複製。
    2) 此時,Slave伺服器的IO執行緒會通過在master上已經授權的複製使用者許可權請求連線master伺服器,並請求從執行binlog日誌檔案的指定位置(日誌檔名和位置就是在配置主從複製服務時執行change master命令指定的)之後開始傳送binlog日誌內容
    3) Master伺服器接收到來自Slave伺服器的IO執行緒的請求後,其上負責複製的IO執行緒會根據Slave伺服器的IO執行緒請求的資訊分批讀取指定binlog日誌檔案指定位置之後的binlog日誌資訊,然後返回給Slave端的IO執行緒。返回的資訊中除了binlog日誌內容外,還有在Master伺服器端記錄的IO執行緒。返回的資訊中除了binlog中的下一個指定更新位置。
    4) 當Slave伺服器的IO執行緒獲取到Master伺服器上IO執行緒傳送的日誌內容、日誌檔案及位置點後,會將binlog日誌內容依次寫到Slave端自身的Relay Log(即中繼日誌)檔案(Mysql-relay-bin.xxx)的最末端,並將新的binlog檔名和位置記錄到master-info檔案中,以便下一次讀取master端新binlog日誌時能告訴Master伺服器從新binlog日誌的指定檔案及位置開始讀取新的binlog日誌內容
    5) Slave伺服器端的SQL執行緒會實時檢測本地Relay Log 中IO執行緒新增的日誌內容,然後及時把Relay LOG 檔案中的內容解析成sql語句,並在自身Slave伺服器上按解析SQL語句的位置順序執行應用這樣sql語句,並在relay-log.info中記錄當前應用中繼日誌的檔名和位置點.
    3.2. 主從複製條件
    • 開啟Binlog功能
    • 主庫要建立賬號
    • 從庫要配置master.info (CHANGE MASTER to...相當於配置密碼檔案和Master的相關資訊)
    • start slave 開啟複製功能
      3.3. 主從複製時需要理解
    • 3個執行緒,主庫IO,從庫IO和SQL及作用
    • master.info(從庫)作用
    • relay-log 作用
    • 非同步複製
    • binlog作用 (如果需要級聯需要開啟Binlog)
      3.4. 主從複製時注意事項
    • 主從複製是非同步邏輯的SQL語句級的複製
    • 複製時,主庫有一個I/O執行緒,從庫有兩個執行緒,I/O和SQL執行緒
    • 實現主從複製的必要條件是主庫要開啟記錄binlog功能
    • 作為複製的所有Mysql節點的server-id都不能相同
    • binlog檔案只記錄對資料庫有更改的SQL語句(來自主庫內容的變更),不記錄任何查詢(select,show)語句
      3.5. 徹底解除主從複製關係
    • stop slave;
    • reset slave; 或直接刪除master.info和relay-log.info這兩個檔案;
    • 修改my.cnf刪除主從相關配置引數。
      讓slave不隨MySQL自動啟動
      修改my.cnf 在[mysqld]中增加"skip-slave-start"選項。

主從複製實現後,使用mysqldump備份資料時,注意按照下面方式
修改my.cnf 在[mysqld]中增加"skip-slave-start"選項。

mysqldump --master-data --single-transaction --user=username --password=password dbname> dumpfilename

這樣就可以保留 file 和 position 的資訊,在新搭建一個slave時,還原完資料庫, file 和 position 的資訊也隨之更新,接著再執行"start slave"就可以很迅速的完成增量同步!

需要限定同步哪些資料庫,有3個思路

  • 在執行grant授權的時候就限定資料庫;
  • 在主伺服器上限定binlog_do_db = 資料庫名;
  • 主伺服器上不限定資料庫,在從伺服器上限定replicate-do-db = 資料庫名;
    如果想實現"主-從(主)-從" 這樣的鏈條式結構,需要設定
    log-slave-updates #只有加上它,從前一臺機器上同步過來的資料才能同步到下一臺機器。
    log-bin=/opt/mysql/binlogs/bin-log #二進位制日誌也必須開啟
    log-bin-index=/opt/mysql/binlogs/bin-log.index
    expire_logs_days=14 # 還可以設定一個log儲存週期
  1. Mysql主從同步時過濾部分庫或表的設定
    4.1. Mysql複製過濾
    讓從節點僅僅複製指定的資料庫,或指定資料庫的指定資料表。主伺服器有10個數據庫,而從節點只需要同步其中的一兩個資料庫。這個時候就需要複製過濾。複製過濾器可以在主節點中實現,也可以在從節點中實現。Mysql主從同步部分資料有兩個思路: master只發送需要的;Slave只接收想要的。
    4.2. master主節點
    在主節點的二進位制事件日誌中僅記錄與指定資料庫(資料表)相關的事件日誌,但是主節點的二進位制日誌不完整,沒有記錄所有對主節點的修改操作。如果要使用該方式,則在主節點的配置檔案中新增如下引數:

binlog_do_db=",,"; #資料庫白名單列表,二進位制日誌記錄的資料庫(多資料庫用逗號隔開或重複設定多行),即需要同步的庫.不在內的不同步。(不新增這行表示同步所有)
binlog_ingore_db="
,,"; #資料庫黑名單列表, 二進位制日誌中忽略的資料庫 (多資料庫用逗號隔開或重複設定多行),即不需要同步,要過濾掉的庫.

4.3. slave從節點
從伺服器SQL Thread在Replay中繼日誌中的事件時僅讀取於特定資料庫相關的事件,並應用於本地. (但是浪費I/O ,浪費頻寬) 推薦使用從節點複製過濾相關設定項:

replicate_do_db ="webdb"; #複製庫的白名單. 設定需要複製的資料庫(多資料庫使用逗號隔開或重複設定多行)
replicate_ingore_db ="mysql"; #複製庫的黑名單. 設定需要忽略的複製資料庫 (多資料庫使用逗號隔開或重複設定多行)
replicate_do_table="webdb.user"; #複製表的白名單. 設定需要複製的表(多資料庫使用逗號隔開或重複設定多行)
relicate_ingore_table="webdb.uw"; #複製表的黑名單. 設定需要忽略的複製的表(多資料庫使用逗號隔開或重複設定多行)

replicate-wild-do-table #同replication-do-table功能一樣,但是可以萬用字元. 更高級別的應用,萬用字元,應用到哪一類表的。
replicate-wild-ignore-table #同replication-ignore-table功能一樣,但是可以加萬用字元.

當在主庫存在的庫而從庫不存在的庫同步時,會出現sql錯誤,這時候可以排除或者從庫手動匯入主庫資料庫;
從庫可以使用萬用字元"庫名.%"方式過濾主從同步時某個庫的設定

replicate-wild-do-table=webdb.% #只複製webdb庫下的所有表
replicate-wild-ignore-table=mysql.% #忽略mysql庫下的所有表

特別注意: 生產庫上一般不建議設定過濾規則, 如果非要設定, 強烈建議從庫使用萬用字元方式過濾某個庫

replicate-wild-do-table= "庫名.%"
replicate-wild-ignore-table= "庫名.%"

而不建議從庫使用DB方式過濾某個庫:

replicate_do_db ="庫名"
replicate_ingore_db ="庫名"