Mysql內建的複製功能是構建大型,高性能應用程序的基礎。將Mysql的數據分佈到多個系統上去,這種分佈的機制,是通過將Mysql的某一臺主機的數據複製到其它主機(slaves)上,並重新執行一遍來實現的。複製過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。這些日誌可以記錄發送到從服務器的更新。當一個從服務器連接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,然後封鎖並等待主服務器通知新的更新。
請注意當你進行復制時,所有對複製中的表的更新必須在主服務器上進行。否則,你必須要小心,以避免用戶對主服務器上的表進行的更新與對從服務器上的表所進行的更新之間的衝突。
(2) 基於行的複製:把改變的內容複製過去,而不是把命令在從服務器上執行一遍. 從mysql5.0開始支持
(3) 混合類型的複製: 默認採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。
MySQL複製技術有以下一些特點:
(1) 數據分佈 (Data distribution )
(2) 負載平衡(load balancing)
(3) 備份(Backups)
(4) 高可用性和容錯行 High availability and failover
1.3 複製如何工作
整體上來說,複製有3個步驟:(1)master將改變記錄到二進制日誌(binary log)中(這些記錄叫做二進制日誌事件,binary log events);
(2)slave將master的binary log events拷貝到它的中繼日誌(relay log);
(3)slave重做中繼日誌中的事件,將改變反映它自己的數據。
下圖描述了複製的過程:
下一步就是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上並行操作。
2.複製配置
有兩臺MySQL數據庫服務器Master和slave,Master爲主服務器,slave爲從服務器,初始狀態時,Master和slave中的數據信息相同,當Master中的數據發生變化時,slave也跟着發生相應的變化,使得master和slave的數據信息同步,達到備份的目的。
負責在主、從服務器傳輸各種修改動作的媒介是主服務器的二進制變更日誌,這個日誌記載着需要傳輸給從服務器的各種修改動作。因此,主服務器必須激活二進制日誌功能。從服務器必須具備足以讓它連接主服務器並請求主服務器把二進制變更日誌傳輸給它的權限。
(1)都從0開始:兩臺新服務器,沒有任何數據;
MariaDB [(none)]> CREATE USER 'tom'@'172.16.41.2' IDENTIFIED BY 'qazwsx123'; MariaDB [(none)]> REVOKE ALL PRIVILEGES ,GRANT OPTION FROM 'tom'@'172.16.41.2'; MariaDB [(none)]> GRANT RELOAD,LOCK TABLES, REPLICATION CLIENT ,REPLICATION SLAVE ON *.* TO 'tom'@'172.16.41.2'; MariaDB [(none)]> FLUSH PRIVILEGES |
(2)啓用二進制日誌
主配置文件/etc/my.cnf [mysqld]段中,修改如下行:
log-bin = /mydata/binlogs/master-bin |
server-id = 1 |
#Slave的配置:
server-id = 2 |
#log-bin = /mydata/mysql-bin //加上註釋 relay-log = /mydata/relaylogs/relay-bin |
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'relay_log'; +---------------+-----------------------------+ | Variable_name | Value | +---------------+-----------------------------+ | relay_log | /mydata/relaylogs/relay-bin | +---------------+-----------------------------+ 1 row in set (0.00 sec) |
(3)連接Master服務器
MariaDB [(none)]> CHANGE MASTER TO MASTER_USER='tom', MASTER_HOST='172.16.41.1', MASTER_PASSWORD='qazwsx123' ; MariaDB [(none)]> SHOW SLAVE STATUS\G; 在輸出的結果當中: Slave_IO_Running: No Slave_SQL_Running: No 表明slave還沒有開始複製過程。日誌的位置爲4而不是0,這是因爲0只是日誌文件的開始位置,並不是日誌位置。實際上,MySQL知道的第一個事件的位置是4。 |
(4)在Slave上面啓動複製線程:
MariaDB [(none)]> START SLAVE; MariaDB [(none)]> SHOW SLAVE STATUS\G slave的I/O和SQL線程都已經開始運行,而且Seconds_Behind_Master不再是NULL。日誌的位置增加了,意味着一些事件被獲取並執行了。如果你在master上進行修改,你可以在slave上看到各種日誌文件的位置的變化,同樣,你也可以看到數據庫中數據的變化。 你可查看master和slave上線程的狀態。在master上,你可以看到slave的I/O線程創建的連接: 在master上輸入show processlist\G; MariaDB [(none)]> SHOW PROCESSLIST\G 行2爲處理slave的I/O線程的連接。 在slave服務器上運行該語句: MariaDB [(none)]> SHOW PROCESSLIST\G 行2爲SQL線程狀態,行3爲I/O線程狀態. |
2.測試
(1)在Master上面創建一個數據庫:
MariaDB [(none)]> CREATE DATABASES testdb1; |
(2)在Slave上面查看:
MariaDB [(none)]> SHOW DATABASES; +--------------------+ |
OK!已經同步過來了,下面爲第二種情況假如master已經運行很久了,想對新安裝的slave進行數據同步,甚至它沒有master的數據。如何指定一個位置開始同步複製:爲了效果我將在Master中導入一些新數據,並且將Slave恢復到最初狀態;
在Master上的操作:
(1)導入新數據:
[root@Master ~]# mysql < hellodb.sql MariaDB [(none)]> SHOW MASTER STATUS; 此時我對數據庫插入一些數據並備份: MariaDB [(none)]> CREATE DATABASE testdb; |
(2)在從服務器上導入:
[root@Slave ~]# mysql < all.sql MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.16.41.1', MASTER_USER='tom', MASTER_PASSWORD='qazwsx123', MASTER_LOG_FILE='master-bin.000001',MASTER_LOG_POS=367; MariaDB [(none)]> START SLAVE; |
OK! 簡單的主從複製到此結束! |
MySQL簡單複製應用擴展: echo "*/5 * * * * /usr/sbin/ntpdate YOUR NTP_SERVER_IP" >> /var/cron/root |
未完,有續!