MySQL如何配置主從複製,主從複製異常如何定位修復?

MySQL如何配置主從複製,如何修復主從複製出現的異常?

一、什麼是Mysql主從複製

MySQL主從複製是其最重要的功能之一。主從複製是指一臺服務器充當主數據庫服務器,另一臺或多臺服務器充當從數據庫服務器,主服務器中的數據自動複製到從服務器之中。對於多級複製,數據庫服務器即可充當主機,也可充當從機。MySQL主從複製的基礎是主服務器對數據庫修改記錄二進制日誌,從服務器通過主服務器的二進制日誌自動執行更新。

二、Mysq主從複製的三種類型

基於語句的複製:
主服務器上面執行的語句在從服務器上面再執行一遍,在MySQL-3.23版本以後支持。

存在的問題:時間上可能不完全同步造成偏差,執行語句的用戶也可能是不同一個用戶。

基於行的複製:
把主服務器上面改編後的內容直接複製過去,而不關心到底改變該內容是由哪條語句引發的,在MySQL-5.0版本以後引入。

存在的問題:比如一個工資表中有一萬個用戶,我們把每個用戶的工資+1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。

混合類型的複製:
MySQL默認使用基於語句的複製,當基於語句的複製會引發問題的時候就會使用基於行的複製,MySQL會自動進行選擇。

在MySQL主從複製架構中,讀操作可以在所有的服務器上面進行,而寫操作只能在主服務器上面進行。主從複製架構雖然給讀操作提供了擴展,可如果寫操作也比較多的話(多臺從服務器還要從主服務器上面同步數據),單主模型的複製中主服務器勢必會成爲性能瓶頸。

三、Mysql主從複製的工作原理

1、基於語句的複製:主服務器上面執行的語句在從服務器上面再執行一遍,在MySQL-3.23版本以後支持。

存在的問題:時間上可能不完全同步造成偏差,執行語句的用戶也可能是不同一個用戶。

2、基於行的複製:把主服務器上面改編後的內容直接複製過去,而不關心到底改變該內容是由哪條語句引發的,在MySQL-5.0版本以後引入。

存在的問題:比如一個工資表中有一萬個用戶,我們把每個用戶的工資+1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。

3、混合類型的複製:MySQL默認使用基於語句的複製,當基於語句的複製會引發問題的時候就會使用基於行的複製,MySQL會自動進行選擇。

在MySQL主從複製架構中,讀操作可以在所有的服務器上面進行,而寫操作只能在主服務器上面進行。主從複製架構雖然給讀操作提供了擴展,可如果寫操作也比較多的話(多臺從服務器還要從主服務器上面同步數據),單主模型的複製中主服務器勢必會成爲性能瓶頸。

配置Master的my.cnf文件(關鍵性的配置)/etc/my.cnf

log-bin=mysql-bin

server-id   = 1

binlog-do-db=icinga

binlog-do-db=DB2     //如果備份多個數據庫,重複設置這個選項即可

binlog-do-db=DB3   //需要同步的數據庫,如果沒有本行,即表示同步所有的數據庫

binlog-ignore-db=mysql  //被忽略的數據庫

配置Slave的my.cnf文件(關鍵性的配置)/etc/my.cnf

log-bin=mysql-bin

server-id=2

master-host=10.1.68.110

master-user=backup

master-password=1234qwer

master-port=3306

replicate-do-db=icinga

replicate-do-db=DB2

replicate-do-db=DB3   //需要同步的數據庫,如果沒有本行,即表示同步所有的數據庫

replicate-ignore-db=mysql   //被忽略的數據庫

建議:複製時若需要忽略某些數據庫或者表的操作,最好不要在主服務器上面配置,因爲主服務器忽略之後就不會再往二進制文件中寫了,但是在從服務器上面雖然忽略了某些數據庫但是主服務器上面的這些操作信息依然會被複制到從服務器上面的relay log裏面,只是不會在從服務器上面執行而已。建議在從服務器中設置replicate-do-db,而不要在主服務器上設置binlog-do-db
不管是黑名單(binlog-ignore-db、replicate-ignore-db)還是白名單(binlog-do-db、replicate-do-db)只寫一個就行了,如果同時使用那麼只有白名單生效。

四、Mysql主從複製的過程

MySQL主從複製的兩種情況:同步複製和異步複製,實際複製架構中大部分爲異步複製。

複製的基本過程如下:

  1. Slave上面的IO進程連接上Master,並請求從指定日誌文件的指定位置(或者從最開始的日誌)之後的日誌內容。

  2. Master接收到來自Slave的IO進程的請求後,負責複製的IO進程會根據請求信息讀取日誌指定位置之後的日誌信息,返回給Slave的IO進程。返回信息中除了日誌所包含的信息之外,還包括本次返回的信息已經到Master端的bin-log文件的名稱以及bin-log的位置。

  3. Slave的IO進程接收到信息後,將接收到的日誌內容依次添加到Slave端的relay-log文件的最末端,並將讀取到的Master端的 bin-log的文件名和位置記錄到master-info文件中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個bin-log的哪個位置開始往後的日誌內容,請發給我”。

  4. Slave的Sql進程檢測到relay-log中新增加了內容後,會馬上解析relay-log的內容成爲在Master端真實執行時候的那些可執行的內容,並在自身執行。

五、Mysql主從複製的具體配置
複製通常用來創建主節點的副本,通過添加冗餘節點來保證高可用性,當然複製也可以用於其他用途,例如在從節點上進行數據讀、分析等等。在橫向擴展的業務中,複製很容易實施,主要表現在在利用主節點進行寫操作,多個從節點進行讀操作,MySQL複製的異步性是指:事物首先在主節點上提交,然後複製給從節點並在從節點上應用,這樣意味着在同一個時間點主從上的數據可能不一致。異步複製的好處在於它比同步複製要快,如果對數據的一致性要求很高,還是採用同步複製較好。

最簡單的複製模式就是一主一從的複製模式了,這樣一個簡單的架構只需要三個步驟即可完成:

  1. 建立一個主節點,開啓binlog,設置服務器id;
  2. 建立一個從節點,設置服務器id;
  3. 將從節點連接到主節點上。

Master機器
Master上面開啓binlog日誌,並且設置一個唯一的服務器id,在局域網內這個id必須唯一。二進制的binlog日誌記錄master上的所有數據庫改變,這個日誌會被複制到從節點上,並且在從節點上回放。修改my.cnf文件,在mysqld模塊下修改如下內容:

[mysqld]
server-id   = 1
log_bin     = /var/log/mysql/mysql-bin.log

Slave機器
slave機器和master一樣,需要一個唯一的server-id。

[mysqld]
server-id = 2

連接Slave到Master
在Master和Slave都配置好後,只需要把slave連接master即可
mysql> change master to master_host='XXXX',master_port=3306,master_user='account',master_password='XXXpassword';

接下來在master上做一些針對改變數據庫的操作,來觀察slave的變化情況。在修改完my.cnf配置重啓數據庫後,就開始記錄binlog了。可以在/var/log/mysql目錄下看到一個mysql-bin.000001文件,而且還有一個mysql-bin.index文件,這個mysql-bin.index文件是什麼?這個文件保存了所有的binlog文件列表,但是我們在配置文件中並沒有設置改值,這個可以通過log_bin_index進行設置,如果沒有設置改值,則默認值和log_bin一樣。在master上執行show binlog events命令,可以看到第一個binlog文件的內容。

注意:上面的sql語句是從頭開始複製第一個binlog。若當前主庫已經有部分binlog數據。
如果想從主庫當前位置開始複製binlog,可以使用SHOW MASTER STATUS;查看主庫當前binlog的文件位置。
如果想從主庫某個位置開始複製binlog,就需要在change master to時指定要開始的binlog文件名和語句在文件中的起點位置,參數如下:master_log_file和master_log_pos。

mysql> show binlog events\G
*************************** 1. row ***************************
   Log_name: mysql-bin.000001
        Pos: 4
 Event_type: Format_desc
  Server_id: 1
End_log_pos: 107
       Info: Server ver: 5.5.28-0ubuntu0.12.10.2-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: mysql-bin.000001
        Pos: 107
 Event_type: Query
  Server_id: 1
End_log_pos: 181
       Info: create user rep
*************************** 3. row ***************************
   Log_name: mysql-bin.000001
        Pos: 181
 Event_type: Query
  Server_id: 1
End_log_pos: 316
       Info: grant replication slave on *.* to rep identified by '123456'
3 rows in set (0.00 sec)
  • Log_name 是二進制日誌文件的名稱,一個事件不能橫跨兩個文件
  • Pos 這是該事件在文件中的開始位置
  • Event_type 事件的類型,事件類型是給slave傳遞信息的基本方法,每個新的binlog都已Format_desc類型開始,以Rotate類型結束
  • Server_id 創建該事件的服務器id
  • End_log_pos 該事件的結束位置,也是下一個事件的開始位置,因此事件範圍爲Pos~End_log_pos-1
  • Info 事件信息的可讀文本,不同的事件有不同的信息
mysql> change master to 
master_host='XXXX',
master_port=3306,
master_user='account',
master_password='XXXpassword',
master_log_file=xxxxxxfilename,
master_log_pos=xxxx;

然後開始同步:

mysql> start slave;

此時我們在主庫執行一條sql語句,從庫也會出現相同的結果。

五 MySQL主從複製的類型

五 MySQL主從複製錯誤及處理辦法

主從複製什麼時候會出現錯誤呢?
當在主庫執行一條sql語句成功,但從庫複製的時候,發現從庫執行這條sql語句出現異常,可能出現的原因是:當表不存在、唯一索引衝突等情況時。

再此情況下,我們首先需要定位當前究竟什麼什麼原因導致從庫複製失敗。
現在從庫執行:show slave status\G 獲取從庫的複製狀態
返回的結果中,我們首先需要關注:Last_SQL_Error 代表最後一個執行的sql出錯的原因。

定位到了錯誤的原因,我們需要根據錯誤原因,解決問題。這裏我們需要關注三個返回值:

Relay_Master_Log_File: mysql-bin.000001
Skip_Counter: 0
Exec_Master_Log_Pos: 1543

Relay_Master_Log_File表示主庫哪個日誌文件出現問題,
Exec_Master_Log_Pos表示偏移量

根據以上提示的信息,在主庫執行
mysql> SHOW BINLOG EVENTS in 'mysql-bin.000001' from 1543;
可以看到出錯的sql語句,MySQL的binary log每個SQL執行實際上是由一些event組成的,我們這裏要設置的就是要跳過的event的個數。本例中就是BEGIN、具體SQL語句和COMMIT這3個event,因此我們可以在從庫上執行:

mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 3;

即可跳過這個語句
然後再次開啓同步:

mysql> start slave;

再執行:

mysql> show slave status\G

檢查從庫同步狀態。

上一篇:MySQL如何開啓binlog?binlog三種模式的分析

下一篇:主庫已有數據時,如何進行主備複製?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章