程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 淺析MySQL復制,淺析mysql

淺析MySQL復制,淺析mysql

編輯:MySQL綜合教程

淺析MySQL復制,淺析mysql


MySQL的復制是基於binlog來實現的。

 

流程如下

涉及到三個線程,主庫的DUMP線程,從庫的IO線程和SQL線程。

1. 主庫將所有操作都記錄到binlog中。當復制開啟時,主庫的DUMP線程根據從庫IO線程的請求將binlog中的內容發送到從庫。

2. 從庫的IO線程接受到主庫DUMP線程發送的binlog事件後,將其寫到本地的relay-log。

3. 從庫的SQL線程重放relay-log中的事件。

實際上,在MySQL 4.0之前,復制只有兩個線程,master和slave端各一個。在Slave端,該線程同時負責接收主庫發來的binlog事件,也負責事件的重放,所以沒有使用relay-log,這樣容易導致,當binlog事件的重放速度較慢時,會影響binlog事件的接受。

 

復制的搭建

基本步驟如下:

1. 配置主庫和從庫

2. 創建復制的賬號

3. 創建主庫一致性快照

4. 根據主庫的快照,建立從庫

5. 開啟復制

 

詳細步驟如下

1. 配置主庫和從庫

主庫

開啟binlog並設置server-id

[mysqld]
log-bin=mysql-bin
server-id=1

在一組復制結構中,每個服務器必須配置一個唯一的server-id。該值的有效范圍為1~232-1。

如果server-id設置為0的話,則MySQL會自動將它更改為1。此時,對復制沒有影響。

如果server-id沒有顯式設置的話,則MySQL同樣會將它設置為1,但是從連接的時候,IO線程會報錯

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Misconfigured master - server_id was not set'

 

從庫

設置server-id

[mysqld]
server-id=2

在從服務器上,可以選擇不開啟binlog。當開啟了binlog後,如果想把重放的時間同樣也記錄到binlog中,可將log_slave_updates參數設置為1。

 

設置完畢後,重啟數據庫

 

2. 創建復制賬號

主庫上執行

mysql> CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';

 

3. 創建主庫一致性快照

在這裡,我用mysqldump來創建數據庫快照

# mysqldump --master-data=2  -R --single-transaction -A > 3306_20160815.sql

在生成的備份文件中,我們可以得到在對數據庫執行一致性快照時主的狀態,包括二進制文件的名稱及位置

# head -30 3306_20160815.sql

...
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=120;
...

 

4. 根據主庫的快照,建立從庫

# mysql < 3306_20160815.sql

 

5. 開啟復制

根據第3步獲取到的主庫狀態執行CHANGE MASTER TO命令

mysql> CHANGE MASTER TO
         MASTER_HOST='master_host_name',
         MASTER_USER='replication_user_name',
         MASTER_PASSWORD='replication_password',
         MASTER_LOG_FILE='recorded_log_file_name',
         MASTER_LOG_POS=recorded_log_position;

在執行CHANGE MASTER TO命令後,從庫並不會連接到主庫,而只是將這些信息寫入到從庫數據目錄下的master.info和relay-log.info中。如果沒有顯式指定MASTER_LOG_FILE,則默認為空,因為此時還沒有和主庫建立連接,並不知道主庫binlog的文件名稱,只有等到和主庫建立連接時才能知道。如果MASTER_LOG_POS沒有顯式指定,則默認為4,即忽略binlog的頭4個字節,從第一個事件開始讀取。

 

開啟復制功能

mysql> start slave;

 

查看復制的狀態

mysql> show slave status\G

重點關注以下兩個變量,如果為YES,則代表復制搭建成功。

...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...

 

注:以上搭建場景是基於主庫上已經有一定的數據。如果在全新的環境中搭建,實際上會更簡單。

只需獲取主庫的狀態信息即可

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000016 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec

 

MySQL復制的格式

MySQL的復制有三種格式:

Statement-based replication(SBR)

基於語句的復制,即master上執行的SQL語句原封不動的在slave上重放。該復制格式在MySQL 3.23即出現了。

優點:

1. 節省binlog的空間。

2. 可用於審核,畢竟所有的DML語句都是直接記錄在binlog中。

缺點:

1. 很多函數在主從上執行的結果並不一致

LOAD_FILE(),UUID(), UUID_SHORT(),USER(),FOUND_ROWS(),SYSDATE(),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),MASTER_POS_WAIT(),RAND(),RELEASE_LOCK(),SLEEP(),VERSION()

2. DELETE和UPDATE操作,帶了LIMIT子句,卻沒有帶ORDER BY,可能導致主從執行的結果並不一致。

3. 相對於基於行的復制,master上執行INSERT ... SELECT操作需要更多的行鎖。

4. 自定義函數(UDF)必須確保執行的結果是確定的。

 

Row-based replication(RBR)

基於行的復制,MySQL 5.1引入的,相對於SBR,它記錄的是DML操作涉及到的行。

優點:

1. 安全。master上所有的變更都能復制到slave上。

2. 在執行以下操作時,只需更少的行鎖。

    INSERT ... SELECT

    帶有AUTO_INCREMENT列的INSERT操作

    UPDATE和DELETE中,WHERE條件沒有用上索引。

缺點:

1. 會產生大量的日志。

譬如一張表有1w條記錄,如果我不帶任何條件執行delete操作,則在基於statement的復制中,在binlog中只會記錄delete from table這一條記錄,但是在基於row的復制中,則會記錄1w筆記錄,每筆記錄類似於delete from table where ..。

這會帶來以下問題

 1> 如果利用binlog進行恢復,會需要更長的時間.

 2> 在寫數據到binlog中時,因為數據量大,會導致binlog的鎖定時間較長,影響數據庫的並發。

 3> 較大的日志會對磁盤IO和網絡IO產生較大的壓力。

 4> 增大slave的延遲。

2. 不會對二進制日志進行校驗。

3. 不推薦基於庫級別的復制

    包括--replicate-do-db, --replicate-ignore-db, --replicate-rewrite-db

 

MIXED

MIXED是上述兩者的的結合,會根據執行的語句和涉及的存儲引擎自動在這兩種模式間切換。默認情況下,采用的是基於語句的復制模式,在遇到unsafe statements時,會切換為基於行的復制模式。

關於切換的條件,可參考官方文檔:http://dev.mysql.com/doc/refman/5.7/en/binary-log-mixed.html

 

在MySQL 5.7.7之前,默認的是基於語句的復制模式,從MySQL 5.7.7開始,默認基於行的復制模式。

 

復制中涉及的文件

relay-log

relay-log保存著從庫IO線程從主庫讀取到的binlog事件。和binlog格式一樣,可通過mysqlbinlog解析其中的內容。

可通過配置relay_log和relay_log_index參數設置relay-log和relay-log.index文件的名稱。

 

relay-log在如下情況下會發生切換:

1. slave IO線程啟動的時候。

2. 執行FLUSH LOGS操作的時候。

3. 達到參數max_relay_log_size設置的大小,默認為0,即以max_binlog_size的值作為max_relay_log_size的大小。

slave SQL線程在重放完一個relay-log文件中的所有事件後,會自動刪除relay-log文件(由relay_log_purge參數控制),所以沒有顯式刪除relay-log的命令。

 

master.info

該文件保存了主庫的主機名,端口,復制賬號的用戶名和密碼,以及從庫接受主庫binlog事件的位置信息,通過這些位置信息,從庫的IO線程知道下次從哪裡獲取主庫的binlog事件。

該位置信息對應於show slave status\G中的Master_Log_File和Read_Master_Log_Pos。

如下所示:

# cat master.info

23
mysql-bin.000014
120
192.168.244.10
repl
repl
3306
60
0





0
1800.000

0
cad449f2-5d4f-11e6-b353-000c29c64704
86400


0

 

relay-log.info

該文件記錄從庫的重放信息,這樣即便數據庫發生重啟,SQL線程也知道該從哪裡開始重放。

該位置信息對應於show slave status\G中的Relay_Master_Log_File和Exec_Master_Log_Pos。

# cat relay-log.info

7
./mysqld-relay-bin.000024
283
mysql-bin.000014
120
0
0
1
1

 

Crash-Safe Replication

slave每次接受binlog或者應用relay-log時,都要修改master.info或relay-log.info的信息並同步到磁盤中,這會導致大量的磁盤操作,所以,一般都是采用異步方式來對這兩個文件進行更改。雖然每次都會修改這些文件,但是持久化到磁盤卻留給操作系統處理。在內存與磁盤中的信息不一致時,如果此時操作系統宕機,內存中的信息將無法及時同步到磁盤中。操作系統恢復後,master.info和relay-log.info的數據依然是舊的,所以會從已經執行的部分重新執行。

MySQL 5.6為了改善這個問題,提供了兩個參數,可將master.info和relay-log.info中的內容保存在表中而不是磁盤文件中。

master-info-repository

可設置為TABLE或FILE,如果使用FILE,則復制的位置信息依舊保存在master.info中,如果設置為TABLE,則信息報保存在mysql.slave_master_info中,默認為FILE。

relay-log-info-repository

可設置為TABLE或FILE,如果使用FILE,則應用relay-log的信息會保存在relay-log.info中,如果設置為TABLE,則保存在mysql.slave_relay_log_info中,默認為FILE。

 

通過將上述兩個變量設置為TABLE,可實現“Crash-Safe Replication”,上述的相關操作都會放到一個事務中進行。

 

總結

1. 啟用復制功能並不會增加服務器太多的開銷,主要是開啟binlog帶來的開銷,包括binlog文件的追加寫操作開銷,以及系統調用fsync帶來的開銷。

2. MySQL的復制功能具有向後兼容性,因為較新版本的MySQL的binlog中會進入新的事件類型。所以,可以將較新版本的MySQL作為從庫。

3. MySQL復制是異步的。

4. MySQL 5.6開始新增延遲復制功能,由master_delay參數來控制。

 

參考

1. http://dev.mysql.com/doc/refman/5.7/en/replication-configuration.html

2. MariaDB原理與實現

 

 

 

 

 

 

 

 

 

    

    

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved