Mysql內建的復制功能是構建大型,高性能應用程序的基礎。將Mysql的數據分布到多個系統上去,這種分布的機制,是通過將Mysql的某一台主機的數據復制到其它主機(slaves)上,並重新執行一遍來實現的。復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日志文件,並維護文件的一個索引以跟蹤日志循環。這些日志可以記錄發送到從服務器的更新。當一個從服務器連接主服務器時,它通知主服務器從服務器在日志中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,然後封鎖並等待主服務器通知新的更新。
請注意當你進行復制時,所有對復制中的表的更新必須在主服務器上進行。否則,你必須要小心,以避免用戶對主服務器上的表進行的更新與對從服務器上的表所進行的更新之間的沖突。
(1):基於語句的復制: 在主服務器上執行的SQL語句,在從服務器上執行同樣的語句。MySQL默認采用基於語句的復制,效率比較高。
一旦發現沒法精確復制時, 會自動選著基於行的復制。
(2):基於行的復制:把改變的內容復制過去,而不是把命令在從服務器上執行一遍. 從mysql5.0開始支持
(3):混合類型的復制: 默認采用基於語句的復制,一旦發現基於語句的無法精確的復制時,就會采用基於行的復制。
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重做中繼日志中的事件,將改變反映它自己的數據。
下圖描述了復制的過程:
該過程的第一部分就是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上並行操作。
有兩台MySQL數據庫服務器Master和slave,Master為主服務器,slave為從服務器,初始狀態時,Master和slave中的數據信息相同,當Master 中的數據發生變化時,slave也跟著發生相應的變化,使得master和slave的數據信息同步,達到備份的目的。
要點:
負責在主、從服務器傳輸各種修改動作的媒介是主服務器的二進制變更日志,這個日志記載著需要傳輸給從服務器的各種修改動作。因此,主服務器必須激活二進制日志功能。從服務器必須具備足以讓它連接主服務器並請求主服務器把二進制變更日志傳輸給它的權限。
1、在Master的數據庫中建立一個備份帳戶:每個slave使用標准的MySQL用戶名和密碼連接master。進行復制操作的用戶會授予REPLICATIONSLAVE權限。用戶名的密碼都會存儲在文本文件master.info中
命令如下:
mysql > GRANT REPLICATIONSLAVE,RELOAD,SUPER ON *.* TO backup@'192.168.43.129' IDENTIFIED BY '1234';
建立一個帳戶backup,並且只能允許從192.168.43.129這個地址上來登陸,密碼是1234。
(如果因為mysql版本新舊密碼算法不同,可以設置:set password for 'backup'@'192.168.43.129'=old_password('1234'))
接下來對master進行配置,包括打開二進制日志,指定唯一的servr ID。例如,在配置文件加入如下值:
server-id=10 log-bin=mysql-bin
server-id:為主服務器A的ID值
log-bin:二進制變更日值
重啟master,運行SHOWMASTER STATUS,輸出如下:
Slave的配置與master類似,你同樣需要重啟slave的MySQL。如下:
log_bin = mysql-bin server_id = 2 relay_log = mysql-relay-bin log_slave_updates = 1 read_only = 1server_id 是必須的,而且唯一。slave沒有必要開啟二進制日志,但是在一些情況下,必須設置,例如,如果slave為其它slave的master,必須設置 bin_log。在這裡,我們開啟了二進制日志,而且顯示的命名(默認名稱為hostname,但是,如果hostname改變則會出現問題)。
(假如是你完全新安裝mysql主從服務器,這個一步就不需要。因為新安裝的master和slave有相同的數據)
拷貝數據大概分為以下幾個方法
關停Master服務器,將Master中的數據拷貝到B服務器中,使得Master和slave中的數據同步,這個方法的問題比較明顯,需要重啟主庫服務器
如果數據庫中的表用的都是MYISAM表,可以在主庫運行時,使用mysqlhotcopy或者是 rsync來復制數據
如果只使用innodb,可以使用下面的命令來執行復制
mysqldump -u root -p --single-transaction --all-databases --add-drop-database --disable-keys --flush-privileges --quick --routines --triggers | mysql -h 192.168.43.129 -u root –p
在復制的過程中如果遇到“1130 HY000”異常,可參見http://blog.csdn.net/eric_sunah/article/details/18567091
禁止在Master和slave服務器中進行寫操作,使得兩數據庫中的數據一定要相同!
接下來就是讓slave連接master,並開始重做master二進制日志中的事件。你不應該用配置文件進行該操作,而應該使用CHANGE MASTER TO語句,該語句可以完全取代對配置文件的修改,而且它可以為slave指定不同的master,而不需要停止服務器。如下:
mysql> CHANGE MASTER TO MASTER_HOST='server1', -> MASTER_USER='backup', -> MASTER_PASSWORD='1234', -> MASTER_LOG_FILE='mysql-bin.000001', -> MASTER_LOG_POS=0;
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;
運行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
在這裡主要是看:
Slave_IO_Running=Yes
Slave_SQL_Running=Yes
slave的I/O和SQL線程都已經開始運行,而且Seconds_Behind_Master不再是NULL。日志的位置增加了,意味著一些事件被獲取並執行了。如果你在master上進行修改,你可以在slave上看到各種日志文件的位置的變化,同樣,你也可以看到數據庫中數據的變化。
你可查看master和slave上線程的狀態。在master上,你可以看到slave的I/O線程創建的連接:
在master上輸入show processlist\G;
mysql> show processlist \G
*************************** 1. row ***************************
Id: 1
User: root
Host: localhost:2096
db: test
Command: Query
Time: 0
State: NULL
Info: show processlist
*************************** 2. row ***************************
Id: 2
User: repl
Host: localhost:2144
db: NULL
Command: Binlog Dump
Time: 1838
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
2 rows in set (0.00 sec)
行2為處理slave的I/O線程的連接。
在slave服務器上運行該語句:
mysql> show processlist \G
*************************** 1. row ***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 2291
State: Waiting for master to send event