快速理解mysql主從,主主備份原理及實踐

    雙機熱備的概念簡單說一下,就是要保持兩個數據庫的狀態自動同步。對任何一個數據庫的操作都自動應用到另外一個數據庫,始終保持兩個數據庫數據一致。 這樣做的好處多。 

    1. 可以做災備,其中一個壞了可以切換到另一個。 

    2. 可以做負載均衡,可以將請求分攤到其中任何一臺上,提高網站吞吐量。  對於異地熱備,尤其適合災備。

廢話不多說了。我們直接進入主題。 我們會主要介紹兩部分內容:


image

一, mysql 備份工作原理

    簡單的說就是把一個服務器上執行過的sql語句在別的服務器上也重複執行一遍, 這樣只要兩個數據庫的初態是一樣的,那麼它們就能一直同步。

 

當然這種複製和重複都是mysql自動實現的,我們只需要配置即可。

 

我們進一步詳細介紹原理的細節, 這有一張圖:

上圖中有兩個服務器, 演示了從一個主服務器(master) 把數據同步到從服務器(slave)的過程。

Replication 線程

  Mysql 的 Replication 是一個異步的複製過程,從一個 Mysql instace(我們稱之爲 Master)複製到另一個 Mysql instance(我們稱之 Slave)。在 Master 與 Slave 之間的實現整個複製過程主要由三個線程來完成,其中兩個線程(Sql線程和IO線程)在 Slave 端,另外一個線程(IO線程)在 Master 端。

  要實現 MySQL 的 Replication ,首先必須打開 Master 端的Binary Log(mysql-bin.xxxxxx)功能,否則無法實現。因爲整個複製過程實際上就是Slave從Master端獲取該日誌然後再在自己身上完全 順序的執行日誌中所記錄的各種操作。打開 MySQL 的 Binary Log 可以通過在啓動 MySQL Server 的過程中使用 “—log-bin” 參數選項,或者在 my.cnf 配置文件中的 mysqld 參數組([mysqld]標識後的參數部分)增加 “log-bin” 參數項。


MySQL 複製的基本過程如下:

   1. Slave 上面的IO線程連接上 Master,並請求從指定日誌文件的指定位置(或者從最開始的日誌)之後的日誌內容;、       2. Master 接收到來自 Slave 的 IO 線程的請求後,通過負責複製的 IO 線程根據請求信息讀取指定日誌指定位置之後的日誌信息,返回給 Slave 端的 IO 線程。返回信息中除了日誌所包含的信息之外,還包括本次返回的信息在 Master 端的 Binary Log 文件的名稱以及在 Binary Log 中的位置;

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

    4. Slave 的 SQL 線程檢測到 Relay Log 中新增加了內容後,會馬上解析該 Log 文件中的內容成爲在 Master 端真實執行時候的那些可執行的 Query 語句,並在自身執行這些 Query。這樣,實際上就是在 Master 端和 Slave 端執行了同樣的 Query,所以兩端的數據是完全一樣的。

 

在mysql上可以查看當前服務器的主,從狀態。 其實就是當前服務器的 Binary(作爲主服務器角色)狀態和位置。 以及其RelayLog(作爲從服務器)的複製進度。

 

例如我們在主服務器上查看主狀態:

image

mysql> show master status\G
*************************** 1. row ***************************
            File: mysql-bin.000014
        Position: 107
    Binlog_Do_DB: 
Binlog_Ignore_DB: mysql,information_schema,performance_schema,amh
1 row in set (0.00 sec)

稍微解釋一下這幾行的意思:

1. 第一行表明 當前正在記錄的 binarylog文件名是: mysql-bin.000014.

我們可以在mysql數據目錄下,找到這個文件:

image

2.  第二行, 107. 表示當前的文件偏移量, 就是寫入在mysql-bin.000014 文件的記錄位置。

這兩點就構成了 主服務器的狀態。  配置從服務器的時候,需要用到這兩個值。 告訴從服務器從哪讀取主服務器的數據。 (從服務器會登錄之後,找到這個日誌文件,並從這個偏移量之後開始複製。)

 

3. 第三行,和第四行,表示需要記錄的數據庫和需要忽略的數據庫。 只有需要記錄的數據庫,其變化纔會被寫入到mysql-bin.000014日誌文件中。  後面會再次介紹這兩個參數。

 

我們還可以在從服務器上,查看從服務器的複製狀態。

image

   1:  mysql> show slave status\G
   2:  *************************** 1. row ***************************
   3:                 Slave_IO_State: Waiting for master to send event
   4:                    Master_Host: 198.**.***.***
   5:                    Master_User: r*******
   6:                    Master_Port: 3306
   7:                  Connect_Retry: 60
   8:                Master_Log_File: mysql-bin.000014
   9:            Read_Master_Log_Pos: 107
  10:                 Relay_Log_File: mysqld-relay-bin.000013
  11:                  Relay_Log_Pos: 253
  12:          Relay_Master_Log_File: mysql-bin.000014
  13:               Slave_IO_Running: Yes
  14:              Slave_SQL_Running: Yes
  15:                Replicate_Do_DB:
  16:            Replicate_Ignore_DB: mysql,information_schema,amh,performance_schema
  17:             Replicate_Do_Table:
  18:         Replicate_Ignore_Table:
  19:        Replicate_Wild_Do_Table:
  20:    Replicate_Wild_Ignore_Table:
  21:                     Last_Errno: 0
  22:                     Last_Error:
  23:                   Skip_Counter: 0
  24:            Exec_Master_Log_Pos: 107
  25:                Relay_Log_Space: 556
  26:                Until_Condition: None
  27:                 Until_Log_File:
  28:                  Until_Log_Pos: 0
  29:             Master_SSL_Allowed: No

 

我們還是來重點解釋途中的紅圈的部分:

1.  Master_host 指的是 主服務器的地址。 

2. Master_user 指的是主服務器上用來複制的用戶。  從服務器會用此賬號來登錄主服務。進行復制。

3. Master_log_file 就是前面提到的, 主服務器上的日誌文件名.

4. Read_Master_log_pos 就是前面提到的主服務器的日誌記錄位置, 從服務器根據這兩個條件來選擇複製的文件和位置。

5. Slave_IO_Running:  指的就是從服務器上負責讀取主服務器的線程工作狀態。 從服務器用這個專門的線程鏈接到主服務器上,並把日誌拷貝回來。

6. Slave_SQL_Running: 指的就是專門執行sql的線程。 它負責把複製回來的Relaylog執行到自己的數據庫中。 這兩個參數必須都爲Yes 才表明複製在正常工作。

 

其他的參數之後再介紹。

 

二, mysql 雙機熱備實戰

瞭解了上面的原理之後, 我們來實戰。 這裏有兩個重點, 要想同步數據庫狀態, 需要相同的初態,然後配置同步纔有意義。 當然你可以不要初態,這是你的自由。 我們這裏從頭開始配置一遍。

 

image

 

我們先以A服務器爲起點,  配置它的數據庫同步到B。  這就是主-從複製了。 之後再反過來做一次,就可以互相備份了。

 

1, 第一步,

在A上面創建專門用於備份的 用戶:

 

image

grant replication slave on *.* to 'repl_user'@'192.***.***.***' identified by 'hj34$%&mnkb';

 

上面把ip地址換成B機器的ip地址。 只允許B登錄。安全。

用戶名爲: repl_user

密碼爲: hj34$********nkb

這個等會在B上面要用。

 

2. 開啓主服務器的 binarylog。

很多服務器是默認開啓的,我們這裏檢查一下:

打開 /etc/my.cnf

 

image

 

我來解釋一下紅框中的配置:

前面三行, 你可能已經有了。

binlog-do-db 用來表示,只把哪些數據庫的改動記錄到binary日誌中。 可以寫上關注hello數據庫。 但是我把它註釋掉了。 只是展示一下。 可以寫多行,表示關注多個數據庫。

binlog-ignore-db 表示,需要忽略哪些數據庫。我這裏忽略了其他的4個數據庫。

 

後面兩個用於在 雙主(多主循環)互相備份。 因爲每臺數據庫服務器都可能在同一個表中插入數據,如果表有一個自動增長的主鍵,那麼就會在多服務器上出現主鍵衝突。  解決這個問題的辦法就是讓每個數據庫的自增主鍵不連續。  上圖說是, 我假設需要將來可能需要10臺服務器做備份, 所以auto-increment-increment 設爲10.   而 auto-increment-offset=1 表示這臺服務器的序號。 從1開始, 不超過auto-increment-increment。

這樣做之後, 我在這臺服務器上插入的第一個id就是 1, 第二行的id就是 11了, 而不是2.

(同理,在第二臺服務器上插入的第一個id就是2, 第二行就是12, 這個後面再介紹) 這樣就不會出現主鍵衝突了。 後面我們會演示這個id的效果。

 

3.  獲取主服務器狀態, 和同步初態。

假設我現在有這些數據庫在A上面。

如果你是全新安裝的, 那麼不需要同步初態,直接跳過這一步,到後面直接查看主服務器狀態。

這裏我們假設有一個 hello 數據庫作爲初態。

 

image

 

先鎖定 hello數據庫:

FLUSH TABLES WITH READ LOCK;

 image

 

然後導出數據:

我這裏只需要導出hello數據庫, 如果你有多個數據庫作爲初態的話, 需要導出所有這些數據庫:

 

image

 

然後查看A服務器的binary日誌位置:

記住這個文件名和 位置, 等會在從服務器上會用到。

 

image

 

主服務器已經做完了, 可以解除鎖定了:

 

image

 

 

4.  設置從服務器 B 需要複製的數據庫

打開從服務器 B 的 /etc/my.cnf 文件:

 

image 

 

解釋一下上面的內容。

server-id 必須保證每個服務器不一樣。 這可能和循環同步有關。 防止進入死循環。

replicate-do-db 可以指定需要複製的數據庫, 我這裏注掉了。 演示一下。

replicate-ignore-db 複製時需要排除的數據庫, 我使用了,這個。 除開系統的幾個數據庫之外,所有的數據庫都複製。

relay_log 中繼日誌的名字。 前面說到了, 複製線程需要先把遠程的變化拷貝到這個中繼日誌中, 在執行。

log-slave-updates 意思是,中繼日誌執行之後,這些變化是否需要計入自己的binarylog。 當你的B服務器需要作爲另外一個服務器的主服務器的時候需要打開。  就是雙主互相備份,或者多主循環備份。 我們這裏需要, 所以打開。

 

保存, 重啓mysql。

 

 

5. 導入初態, 開始同步。

把剛纔從A服務器上導出的 hello.sql 導入到 B的hello數據庫中, 如果B現在沒有hello數據庫,請先創建一個, 然後再導入:

創建數據庫:

mysql> create database hello default charset utf8;

把hello.sql 上傳到B上, 然後導入:

image

 

如果你剛纔導出了多個數據庫, 需要把他們都一一上傳導入。

 

開啓同步, 在B服務器上執行:

 CHANGE MASTER TO 
       MASTER_HOST='192.***.***.***', 
       MASTER_USER='repl_user', 
       MASTER_PASSWORD='hj3****', 
       MASTER_LOG_FILE='mysql-bin.000004', 
       MASTER_LOG_POS=7145;

image

 

上面幾個參數我就不解釋了。 前面說過了。

 

重啓mysql,  然後查看slave線程開啓了沒:

 

image

 

注意圖中的紅框, 兩個都是Yes, 說明開啓成功。

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

如果其中一個是No, 那就說明不成功。需要查看mysql的錯誤日誌。 我在第一次做的時候就遇到這個問題。有時候密碼填錯了, 有時候防火牆的3306沒有打開。ip地址不對,等等。 都會導致失敗。

 

我們看錯誤日誌: mysql的錯誤日誌一般在:

 

image

文件名應該是你的機器名, 我這裏叫做host1.err 你換成你自己的。

 

到這裏主-從複製已經打開了。 我們先來實驗一下。

我們在A的數據庫裏面去 添加數據:

 

image

我在A的 hello數據庫的test表中 連續插入了3條數據,  注意看他們的自增長id, 分別是1,11,21.  知道這是爲什麼嗎。 前面已經說過了,不懂再回去看。

 

我們去看一下B數據庫有沒有這三條數據:

 

打開B的數據庫:

image

發現已經在這了。 這裏效果不直觀。

 

此時不要在B中修改數據。 我們接着配置從B到A的複製。  如果你只需要主從複製的話, 到這裏就結束了。後面可以不看了。 所有A中的修改都能自動同步到B, 但是對B的修改卻不能同步到A。 因爲是單向的。 如果需要雙向同步的話,需要再做一次從B到A的複製。

 

基本跟上面一樣:我們簡單一點介紹:

 

1. 在B中創建用戶;

image

 

2. 打開 /etc/my.cnf , 開啓B的binarylog:

image

注意紅框中所新添加的部分。

 

3. 我們不需要導出B的初態了,因爲它剛剛纔從A導過來。  直接記住它的master日誌狀態:

 

image

記住這兩個數值,等會在A上面要用。

B服務器就設置完了。

 

4. 登錄到A 服務器。 開啓中繼:

 

image

注意框中心添加的部分, 不解釋了。

 

5. 啓動同步:

image

上面的ip地址是B的ip地址, 因爲A把B當做master了。 不解釋了。

 

然後重啓mysql服務。

然後查看,slave狀態是否正常:

 

image

圖中出現了兩個No。

Slave_IO_Running: No

Slave_SQL_Running: No

說明slave沒有成功, 即,從B到A的同步沒有成功。 我們去查看mysql錯誤日誌,前面說過位置:

 

image

 

找到  機器名.err 文件,打開看看:

image

 

看圖中的error信息。  說找不到中繼日誌文件。

這是因爲我們在配置A的中繼文件時改了中繼文件名,但是mysql沒有同步。解決辦法很簡單。

 

image

 

先停掉mysql服務。  找到這三個文件,把他們刪掉。 一定要先停掉mysql服務。不然還是不成功。你需要重啓一下機器了。 或者手動kill mysqld。

好了, 啓動mysql之後。 我們在來檢查一下slave狀態:

 

image

 

注意圖中兩個大大的Yes。  哈哈。

 

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

 

證明從B到A的複製也成功了。

 

此時我們去B服務器中插入幾條數據試試:

 

image

我在B中插入了兩條數據。 注意看他們的id。  不解釋。

 

然後我們,登錄去A中看看,A數據庫變了沒。

image

可以看到已經自動同步到A了。

 

至此, AB雙主互相熱備就介紹完了。

 

原理其實很簡單,是不是。

 

理解了這個原理, 多機循環互備就簡單了。這裏就不再展開了。

 


 

 

 

參考:

1. mysql-keepalived-實現雙主熱備讀寫分離

http://gitsea.com/2013/06/16/mysql-keepalived-%E5%AE%9E%E7%8E%B0%E5%8F%8C%E4%B8%BB%E7%83%AD%E5%A4%87%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/

 

2. MySQL數據同步【雙主熱備】http://www.cnblogs.com/zhongweiv/archive/2013/02/01/mysql_replication_circular.html

 

3. Mysql雙機熱備實現

http://yunnick.iteye.com/blog/1845301

 

4. 高性能Mysql主從架構的複製原理及配置詳解http://blog.csdn.net/hguisu/article/details/7325124

 

5.   mysql 基於 master-master 的雙機熱備配置


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