目錄:
一、Mysql Replication介紹
二、Mysql Replication架構
(一)Master-MultiSlave(單主到多從)
(二)Master-DistributedMaster-Slave(單主到從到多從)
(三)Tree(單主到多從再到多從)
(四)Master-Master(雙主)
三、Mysql Replication配置測試
(一)Master-MultiSlave(單主到多從)
(二)Master-DistributedMaster-Slave(單主到從到多從)
(三)Master-Master(雙主)
四、Mysql Replication性能測試
(一)測試環境
(二)準備工作
(三)測試方式
(四)性能測試
(五)測試結果
五、問題排除
(一)出現Slave_IO_Running: No
(二)出現Error: ‘Host ’192.168.7.129′ is not allowed to connect to this MySQL server’ errno: 1130 retry-time: 60 retries: 86400
(三)出現Error: ‘Host ’192.168.7.1′ is not allowed to connect to this MySQL server’
(四)出現Could not initialize master info structure
一、 Mysql Replication介紹
MySQL支持單向、異步複製,複製過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。這些日誌可以記錄發送到從服務器的更新。當一個從服務器連接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,然後封鎖並等待主服務器通知新的更新。
如果想要設置鏈式複製服務器,從服務器本身也可以充當主服務器。
請注意當進行復制時,所有對複製中的表的更新必須在主服務器上進行。否則,必須要小心,以避免用戶對主服務器上的表進行的更新與對從服務器上的表所進行的更新之間的衝突。
單向複製有利於健壯性、速度和系統管理:
1、主服務器/從服務器設置增加了健壯性。主服務器出現問題時,可以切換到從服務器作爲備份。
2、通過在主服務器和從服務器之間切分處理客戶查詢的負荷,可以得到更好的客戶響應時間。SELECT查詢可以發送到從服務器以降低主服務器的查詢處理負荷。但修改數據的語句仍然應發送到主服務器,以便主服務器和從服務器保持同步。如果非更新查詢爲主,該負載均衡策略很有效,但一般是更新查詢。
3、使用複製的另一個好處是可以使用一個從服務器執行備份,而不會干擾主服務器。在備份過程中主服務器可以繼續處理更新。
二、 Mysql Replication架構
在實際應用中,可以根據具體的情況靈活地將主/從結構進行變化組合,下面將介紹一些常見的複製架構,萬變不離其宗。
在進行各種部署之前,還需要遵守這麼幾條規則:
1. 一個從服務器只能有一個主服務器。
2. 一個主服務器可以有多個從服務器。
3. 無論是主服務器還是從服務器,都要確保各自的Server ID唯一。
4. 一個從服務器可以將其從主服務器獲得的更新事件,傳遞給其它的從服務器;同時,這個從服務器也可以成爲其他從服務器的主服務器。
(一)Master-MultiSlave(單主到多從)
這種架構是最基礎的主從結構的水平擴展,所有的Slave之間沒有任何聯繫,它們都各自獨立的與唯一的Master進行連接。這種架構適用於讀操作頻繁寫操作相對比較少的應用。
架構圖如圖1所示:
![]()
圖1 M-MSS架構
(二)Master-DistributedMaster-Slave(單主到從到多從)
這種架構其實是源於上面的Master-MutilSlave架構,在這個基礎上又加入了一個具有特殊功能Master,是一種帶有分佈式功能的Master-MutilSlave架構。實際生產環境中,如果Master後面的Slave的數量相當多,這樣就會給Master系統帶來很大的負擔,因爲它要將每次的更新同步到下面的許許多多的Slave上,這樣就會影響其對外提供服務的性能。如果我們將Master的每次更新先同步到一個Master上,然後再由其完成所有Slave的更新。這個特殊的Master使用一種叫做blackhole的存儲引擎,使其具有很強的分發更新的能力。
架構圖如圖2所示:
![]()
圖2 分佈式M-MSS架構
(三)Tree(單主到多從再到多從)
Tree架構,即M-SS-SS,是一個Master後面有一個龐大的Slave羣,於是就將這些Slave按照樹形結構將它們依次排開,基於上面分佈式M-MSS架構。這種架構可以降低Master端的負載,但是它的缺點也是顯而易見的,Slave間的關聯性很強,如果與Master連接的Slave發生故障,那麼和這個Slave相關聯的所有Slave都將不能正常更新。
架構圖如圖3所示:
![]()
圖3 樹形 M-SS-SS架構
(四)Master-Master(雙主)
這種架構實現了Mysql雙向備份。原則上說,作爲從服務器的數據庫版本可以高於主服務器的數據庫版本,但不可以低於主服務器的數據庫版本。所以在這種架構模式下,兩臺服務器的數據庫版本必須一致。
架構圖如圖4所示:
![]()
圖4 M-M架構
基於這種架構,還可以給每一臺主機附加從服務器(即DualMaster-Slave架構),提供一種額外的安全冗餘,也就是說發生故障時除了Master間的切換,也可以在Master和Slave之間切換,同時Slave還可以對外提供讀操作,減輕Master的負擔。
架構圖如圖5所示:
![]()
圖5 MS-MS架構
以上介紹的幾種架構都是在實際生產環境中常會遇到的架構模式,可以根據企業內部的具體情況,合理地採用這些架構,以保證應用高效可靠的運行。
三、 Mysql Replication配置測試
首先,在每臺服務器上安裝Mysql數據庫:
[root@bogon ~]# yum install mysql*
默認安裝的Mysql包含一個空密碼的root用戶和一個匿名用戶,存在安全隱患,需要手動刪除匿名用戶,加密root帳號。如下操作:
啓動Mysql服務:
[root@bogon ~]# service mysqld start
進入Mysql控制檯:
[root@bogon ~]# mysql
選擇mysql數據庫:
mysql> use mysql
刪除匿名用戶:
mysql> delete from user where user=’ ‘;
設置root用戶密碼:
mysql> update user set password=password(‘qqing99′) where user=’root’;
以上操作重啓mysql後生效。
然後針對上面介紹的幾種架構模式分別進行測試其功能。分析以上幾種架構模式,明顯的可以看出第三種Tree架構模式是基於第二種 Master-DistributedMaster-Slave架構模式,所以測試時只測試第二種架構模式。
(一)Master-MultiSlave(單主到多從)
1、測試環境
Master | Slave1 | Slave2 | Slave3 | |
OS | CentOS release 5.6 (Final) | CentOS release 5.4 (Final) | CentOS release 5.4 (Final) | CentOS release 5.4 (Final) |
Hostname | bogon | repli1 | repli12 | repli13 |
IP | 192.168.41.189 | 192.168.7.128 | 192.168.7.129 | 192.168.7.130 |
Mysql-Version | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 |
2、主服務器授權
在Master(bogon)上創建一個用戶並授權從服務器可以連接主服務器並可以進行更新。
mysql> grant replication slave on *.* to repli@’192.168.7.128′ identified by ‘qqing99′;
mysql> grant replication slave on *.* to repli@’192.168.7.129′ identified by ‘qqing99′;
mysql> grant replication slave on *.* to repli@’192.168.7.130′ identified by ‘qqing99′;
然後退出mysql控制檯,停止mysql服務:
mysql> \q
[root@bogon ~]#
service mysqld stop
3、配置Mysql主配置文件/etc/my.cnf
yum方式安裝mysql,其默認主配置文件爲/etc/my.cnf
在/etc/my.cnf配置文件[mysqld]模塊添加如下參數
Master(bogon):
[root@bogon ~]# vim /etc/my.cnf
server-id = 1 #指定服務器的ID(ID唯一)
log-bin = mysql-bin #指定產生binlog日誌文件的前綴
binlog-do-db = discuz #指定日誌文件只對discuz數據庫進行操作(可選)
binlog-ignore-db = mysql #指定日誌文件不對mysql數據庫進行操作(可選)
Slave1(repli1):
[root@repli1 ~]# vim /etc/my.cnf
server-id = 2 #指定服務器的ID
master-host = 192.168.41.189 #主服務器IP地址
master-user = repli #主服務器上創建授權給從服務器的用戶
master-password = “qqing99″ #用戶密碼
master-port = 3306 #連接端口
master-connect-retry = 60 #重試連接的時間
replicate-ignore-db = mysql #忽略同步備份的數據庫
replicate-do-db = discuz #需要同步備份的數據庫(如有多個,可添加 多條記錄)
Slave2(repli2)和Slave3(repli3)的配置除server-id不同外,其它的和Slave1(repli1)的配置相同。
4、數據複製
確保要同步的Master和Slave的數據庫相同,如果不同則要先把Master的數據庫複製到Slave中。可以用mysqldump工具導出數據庫再導入到Slave中,也可以直接打包Master的數據庫再上傳到Slave。如果數據庫較大,則推薦使用第二種方式。但不管是使用哪種方式,在同步前都要先鎖定Master的數據。
啓動mysql服務:
[root@bogon ~]# service mysqld start
鎖定數據,禁止更新:
mysql> flush tables with read lock;
打包數據:
[root@bogon mysql]# tar zcf discuz.tar.gz discuz
上傳數據:
[root@bogon mysql]# scp discuz.tar.gz root@slave:/var/lib/mysql (slave表示從服務器的IP)
在從服務器上解壓:
[root@repli1 mysql]# tar -zxvf discuz.tar.gz
解除鎖定:
mysql> unlock tables;
5、查看同步狀態
啓動Slave服務器,進入mysql控制檯,查看同步狀態。
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.41.189
Master_User: repli
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000015
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000015
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: discuz
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
正常狀態下,看到上面的兩行加粗處,即Slave_IO_Running和Slave_SQL_Running的參數都爲 Yes,就說明主從同步運行正常。
6、同步測試
在master上寫入數據:
Master:
mysql> select * from repli;
+—-+——+——+
| id | name | sex |
+—-+——+——+
| 1 | Tom | boy |
| 2 | Mary | girl |
| 3 | John | boy |
| 4 | Lucy | girl |
+—-+——+——+
4 rows in set (0.00 sec)
mysql> insert into repli values(5,’Lily’,'girl’);
Query OK, 1 row affected (0.00 sec)
在slave上查看結果:
mysql> select * from repli;
+—-+——+——+
| id | name | sex |
+—-+——+——+
| 1 | Tom | boy |
| 2 | Mary | girl |
| 3 | John | boy |
| 4 | Lucy | girl |
| 5 | Lily | girl |
+—-+——+——+
5 rows in set (0.00 sec)
(二)Master-DistributedMaster-Slave(單主到從到多從)
1、測試環境
Master | Master1/Slave1 | Slave2 | Slave3 | |
OS | CentOS release 5.6 (Final) | CentOS release 5.4 (Final) | CentOS release 5.4 (Final) | CentOS release 5.4 (Final) |
Hostname | bogon | repli1 | repli12 | repli13 |
IP | 192.168.41.189 | 192.168.7.128 | 192.168.7.129 | 192.168.7.130 |
Mysql-Version | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 |
2、主服務器授權
在master(bogon)上創建一個用戶,授權從服務器Master1/Slave1(repli2)可以連接主服務器並可以進行更新。
mysql> grant replication slave on *.* to repli@’192.168.7.128′ identified by ‘qqing99′;
在Master1/Slave1(repli1)上創建一個用戶,授權從服務器Slave2(repli2)和Slave3(repli3)可以連接主服務器並可以進行更新。
mysql> grant replication slave on *.* to srepli@’192.168.7.129′ identified by ‘qqing99′;
mysql> grant replication slave on *.* to srepli@’192.168.7.130′ identified by ‘qqing99′;
然後退出mysql控制檯,停止mysql服務:
mysql> \q
[root@bogon ~]#
service mysqld stop
3、配置Mysql主配置文件/etc/my.cnf
在/etc/my.cnf配置文件[mysqld]模塊添加如下參數
Master(bogon):
[root@bogon ~]# vim /etc/my.cnf
server-id = 1 #指定服務器的ID(ID唯一)
log-bin = mysql-bin #指定產生binlog日誌文件的前綴
binlog-do-db = discuz #指定日誌文件只對discuz數據庫進行操作(可選)
binlog-ignore-db = mysql #指定日誌文件不對mysql數據庫進行操作(可選)
Master1/Slave1(repli1):
[root@repli1 ~]# vim /etc/my.cnf
server-id = 2
log-bin = mysql-bin
binlog-do-db = discuz
binlog-ignore-db = mysql
master-host = 192.168.41.189
master-user = repli
master-password = “qqing99″
master-port = 3306
master-connect-retry = 60
replicate-ignore-db = mysql
replicate-do-db = discuz
log-slave-updates
PS:當配置爲A->B->C架構模式時,即B既是A的從服務器又是C的主服務器時,除了需要打開log-bin之外,還需要打開log-slave-updtes。否則,A的更新只能同步到B後無法同步到C。
可以通過在B上使用“show variables like ‘log%’ ”來確認是否已經生效。
mysql> show variables like ‘log%’;
+———————————+——-+
| Variable_name | Value |
+———————————+——-+
| log | OFF |
| log_bin | ON |
| log_bin_trust_function_creators | OFF |
| log_error | |
| log_queries_not_using_indexes | OFF |
| log_slave_updates | ON |
| log_slow_queries | OFF |
| log_warnings | 1 |
+———————————+——-+
8 rows in set (0.01 sec)
Slave2(repli2)和Slave3(repli3)的配置除server-id不同外,其它的都相同,做如下配置:
server-id = 3
master-host = 192.168.7.128
master-user = srepli
master-password = “qqing99″
master-port = 3306
master-connect-retry = 60
replicate-ignore-db = mysql
replicate-do-db = discuz
4、數據複製
分別在Master(bogon)和Master1/Slave1(repli1)上鎖定數據,禁止更新:
mysql> flush tables with read lock;
打包數據:
[root@bogon mysql]# tar zcf discuz.tar.gz discuz
上傳數據:
[root@bogon mysql]# scp discuz.tar.gz root@slave:/var/lib/mysql (slave表示從服務器的IP)
在從服務器上解壓:
[root@repli1 mysql]# tar -zxvf discuz.tar.gz
分別在Master(bogon)和Master1/Slave1(repli1)上解除鎖定:
mysql> unlock tables;
5、查看同步狀態
啓動Slave服務器,進入mysql控制檯,查看同步狀態。
在master1/Slave1(repli1)上查看:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.41.189
Master_User: repli
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000015
Read_Master_Log_Pos: 204
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000015
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: discuz
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 204
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
分別在Slave2和Slave3查看:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.7.1298
Master_User: srepli
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000016
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000016
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: discuz
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
看到Slave_IO_Running和Slave_SQL_Running的參數都爲 Yes,就說明主從同步運行正常。
6、同步測試
在Master(bogon)上進行數據寫入:
mysql> insert into repli values(6,’Jack’,'boy’);
Query OK, 1 row affected (0.00 sec)
在Master1/Slave1、Slave2和Slave3上查看結果:
mysql> select * from repli;
+—-+——+——+
| id | name | sex |
+—-+——+——+
| 1 | Tom | boy |
| 2 | Mary | girl |
| 3 | John | boy |
| 4 | Lucy | girl |
| 5 | Lily | girl |
| 6 | Jack | boy |
+—-+——+——+
6 rows in set (0.00 sec)
(三)Master-Master(雙主)
1、測試環境
Master/Slave | Master1/Slave1 | |
OS | CentOS release 5.6 (Final) | CentOS release 5.4 (Final) |
Hostname | bogon | repli1 |
IP | 192.168.41.189 | 192.168.7.128 |
Mysql-Version | 14.12 Distrib 5.0.77 | 14.12 Distrib 5.0.77 |
2、主服務器授權
分別在Master/Slave和Master1/Slave1上創建一個用戶並授予相應權限。
mysql> grant replication slave on *.* to repli@’192.168.7.128′ identified by ‘qqing99′;
mysql> grant replication slave on *.* to srepli@’192.168.41.189′ identified by ‘qqing99′;
然後退出mysql控制檯,停止mysql服務:
mysql> \q
[root@bogon ~]#
service mysqld stop
3、配置Mysql主配置文件/etc/my.cnf
在/etc/my.cnf配置文件[mysqld]模塊添加如下參數
Master/Slave(bogon):
[root@bogon ~]# vim /etc/my.cnf
server-id = 1
log-bin = mysql-bin
binlog-do-db = discuz
binlog-ignore-db = mysql
master-host = 192.168.7.128
master-user = srepli
master-password = qqing99
master-port = 3306
replicate-ignore-db = mysql
replicate-do-db = discuz
Master1/Slave1(repli1):
[root@repli1 ~]# vim /etc/my.cnf
server-id = 2
log-bin = mysql-bin
binlog-do-db = discuz
binlog-ignore-db = mysql
master-host = 192.168.41.189
master-user = repli
master-password = qqing99
master-port = 3306
replicate-ignore-db = mysql
replicate-do-db = discuz
4、數據複製
分別在Master/Slave和Master1/Slave1上鎖定數據,禁止更新:
mysql> flush tables with read lock;
打包數據:
[root@bogon mysql]# tar zcf discuz.tar.gz discuz
上傳數據:
[root@bogon mysql]# scp discuz.tar.gz [email protected]:/var/lib/mysql
在服務器上解壓:
[root@repli1 mysql]# tar -zxvf discuz.tar.gz
解除鎖定:
mysql> unlock tables;
5、查看同步狀態
啓動Slave服務器,進入mysql控制檯,查看同步狀態。
在Master1/Slave1上查看
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.41.189
Master_User: repli
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000015
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000015
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: discuz
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
在master/Slave上查看:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.7.129
Master_User: srepli
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000017
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000017
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: discuz
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
6、同步測試
在master/Slave上執行:
mysql> update repli set sex=’girl’ where id=6;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
在master1/Slave1上查看:
mysql> select * from repli;
+—-+——+——+
| id | name | sex |
+—-+——+——+
| 1 | Tom | boy |
| 2 | Mary | girl |
| 3 | John | boy |
| 4 | Lucy | girl |
| 5 | Lily | girl |
| 6 | Jack | girl |
+—-+——+——+
6 rows in set (0.00 sec)
在master1/Slave1上執行:
mysql> insert into repli values(7,’Tim’,'boy’);
Query OK, 1 row affected (0.01 sec)
在master/Slave上查看:
mysql> select * from repli;
+—-+——+——+
| id | name | sex |
+—-+——+——+
| 1 | Tom | boy |
| 2 | Mary | girl |
| 3 | John | boy |
| 4 | Lucy | girl |
| 5 | Lily | girl |
| 6 | Jack | girl |
| 7 | Tim | boy |
+—-+——+——+
7 rows in set (0.00 sec)