Mysql內建的複製功能是構建大型,高性能應用程序的基礎。
將Mysql的數據分佈到多個系統上去,這種分佈的機制,是經過將Mysql的某一臺主機的數據複製到其它主機(slaves)上,並從新執行一遍來實現的。mysql
複製過程當中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。這些日誌能夠記錄發送到從服務器的更新。當一個從服務器鏈接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,而後封鎖並等待主服務器通知新的更新。算法
請注意當你進行復制時,全部對複製中的表的更新必須在主服務器上進行。不然,你必需要當心,以免用戶對主服務器上的表進行的更新與對從服務器上的表所進行的更新之間的衝突。sql
(1):基於語句的複製(邏輯複製):在主服務器上執行的SQL語句,在從服務器上執行一樣的語句。
MySQL默認採用基於語句的複製,效率比較高。
一旦發現無法精確複製時,會自動選着基於行的複製。
(2):基於行的複製:把改變的內容複製過去,而不是把命令在從服務器上執行一遍. 從mysql5.1開始支持
(3):混合類型的複製: 默認採用基於語句的複製,一旦發現基於語句的沒法精確的複製時,就會採用基於行的複製。數據庫
1.2 . 複製解決的問題緩存
MySQL複製技術有如下一些特色:
(1) 數據分佈 (Data distribution )
(2) 負載平衡(load balancing)
(3) 備份(Backups)
(4) 高可用性和容錯行 High availability and failover 服務器
總體上來講,複製有3個步驟: 異步
(1) master將改變記錄到二進制日誌(binary log)中
(這些記錄叫作二進制日誌事件,binary log events);
(2) slave將master的binary log events拷貝到它的中繼日誌(relay log);性能
(3) slave重作中繼日誌中的事件,將改變反映它本身的數據。
測試
下圖描述了複製的過程:spa
該過程的第一部分:
在主庫上記錄二進制日誌。在每次準備提交事務完成數據更新前,主庫將數據更新的事件記錄到二進制日誌中。
MySQL將按事務提交的順序而非每條語句的執行順序來記錄二進制日誌,即便事務中的語句都是交叉執行的。
在事件寫入二進制日誌完成後,主庫通知存儲引擎提交事務。
第二步:
備庫將主庫的binary log拷貝到它本地本身的中繼日誌。
首先,備庫開始一個工做線程——I/O線程。I/O線程與主庫創建一個普通的鏈接,
而後在主庫啓動一個特殊的二進制轉儲線程 binlog dump process。
Binlog dump process從主庫的二進制日誌中讀取事件,若是該線程已經跟上主庫,它會睡眠並等待主庫產生新的事件。
備庫I/O線程會將接收到事件寫入中繼日誌。
第三步:
備庫的 SQL slave thread(SQL從線程)處理該過程的最後一步。
SQL線程從中繼日誌讀取事件,並重放其中的事件而更新備庫的數據,使其與主庫中的數據一致。
只要該線程與I/O線程保持一致,中繼日誌一般會位於OS的緩存中,因此中繼日誌的開銷很小。
此外,在master中也有一個工做線程:和其它MySQL的鏈接同樣,slave在master中打開一個鏈接也會使得master開始一個線程。複製過程有一個很重要的限制——複製在slave上是串行化的,也就是說master上的並行更新操做不能在slave上並行操做。
有兩臺MySQL數據庫服務器Master和slave,Master爲主服務器,slave爲從服務器,初始狀態時,Master和slave中的數據信息相同,當Master中的數據發生變化時,slave也跟着發生相應的變化,使得master和slave的數據信息同步,達到備份的目的。
要點:
負責在主、從服務器傳輸各類修改動做的媒介是主服務器的二進制變動日誌,這個日誌記載着須要傳輸給從服務器的各類修改動做。
所以:
主服務器必須激活二進制日誌功能。
從服務器必須具有足以讓它鏈接主服務器並請求主服務器把二進制變動日誌傳輸給它的權限。
準備工做:
1.在每臺服務器上建立 複製帳號
2.配置主庫和備庫
3.通知備庫鏈接到主庫,並從主庫複製數據
一、在主數據庫中創建一個備份賬戶:從庫的I/O線程 使用該備份帳戶 鏈接到主庫。
進行復制操做的備份帳戶會授予REPLICATION SLAVE權限。
用戶名的密碼都會存儲在文本文件master.info中
創建一個賬戶backup,而且只能容許從10.0.0.xxx這個地址上來登錄,密碼是1234。
(若是由於mysql版本新舊密碼算法不一樣,能夠設置:set password for 'backup'@'10.100.0.200'=old_password('1234'))
在從庫一樣創建相同帳戶;
命令以下:
mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
->TO backup@'10.0.0.%' IDENTIFIED BY '1234';
注意:備份帳戶事實上只須要有主庫的 REPLICATION SALVE 權限,
並不必定須要每一端服務器都有REPLICATION CLIENT權限。
replication slave:擁有此權限能夠 查看從服務器,從主服務器讀取二進制日誌。
replication client:擁有此權限能夠 查詢master server、slave server狀態。
爲何要在主從兩個庫 創建相同權限的用戶呢?
未來有須要時 方便主從兩庫交換角色
2.2 配置主庫
接下來對master進行配置,包括打開二進制日誌,指定惟一的servr ID。
在配置文件加入以下值:
server-id=8
log-bin=mysql-bin
#server-id:爲主庫服務器的ID值,默認爲1,這個值不能與其餘服務器衝突;一般採用IP地址末位,
#log-bin:二進制變動日值
重啓master;
運行SHOW MASTER STATUS,輸出以下:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2.3 配置從庫
server_id = 9
log_bin = mysql-bin
relay_log = /var/lib/mysql/mysql-relay-bin
log_slave_updates = 1
read_only
server_id:是必須的,不能重複
log_bin: 二進制日誌並不必定要開啓,可是在一些狀況下,必須設置,
例如,若是slave爲其它slave的master,必須設置bin_log
relay_log: 配置中繼日誌位置和名字
log_slave_updates: 表示slave將複製事件寫進本身的二進制日誌(後面會看到它的用處)。
會增長一些備庫的負載
注意:開啓了slave的二進制日誌,卻沒有開啓log_slave_updates,這可能會出現一些問題,
例如slave的數據被改變。
因此,儘可能使用read_only,它防止改變數據(除了特殊的線程)。
可是,read_only並是很實用,特別是那些須要在slave上建立表的應用。
注意:不要在my.cnf 中設置 master_port或 master_host 這是老的配置方式,已經被廢棄。
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.42',
-> MASTER_USER='backup',
-> MASTER_PASSWORD='1234',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;
能夠用SHOW SLAVE STATUS語句查看slave的設置是否正確:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL
Slave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No
代表slave尚未開始複製過程。日誌的位置爲4而不是0,這是由於0只是日誌文件的開始位置,並非日誌位置。
實際上,MySQL知道的第一個事件的位置是4。
開始複製,你能夠運行:
mysql> START SLAVE;
Query OK, 0 rows affected (0.01 sec)
從庫運行SHOW SLAVE STATUS查看輸出結果:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
行2 爲I/O線程,行3爲SQL線程;
以上的全部操做都是基於兩臺新建立的數據庫服務器,也就是所兩臺數據庫數據相同。
這不是典型的案列,多數狀況下是有一個已經運行一段時間的數據庫,而後用一個新安裝的數據庫和它進行同步,
此時新庫尚未數據,