MySQL主從復制 + Mycat實現讀寫分離
說明:兩臺MySQL服務器都是使用CentOS6.5系統,MySQL版本為mysql-5.7.17
MySQL一主一被實現主從復制
註意:寫包括insert,delete,update 操作;讀只有select其他操作由主master的二進制文件決定。
一.在192.168.42.128上安裝MySQL(主庫)
開啟賬號root的遠程登錄權限,過程:略
配置主服務器的my.cnf 文件 並重啟(開啟二進制文件等)
##------------------------------------------周建旭2017年3月6日 12:40:10添加------------------------------------# # # server-id 唯一的服務辨識號,數值位於 1 到 2^32-1之間. # # 此值在master和slave上都需要設置. # # 如果 “master-host” 沒有被設置,則默認為1, 但是如果忽略此選項,MySQL不會作為master生效. server-id = 1 #[必須]服務器唯一ID,默認是1 ##------------------------------------------master上的配置開始------------------------------------------------## # # # # log-bin 打開二進制日誌功能. # # # 在復制(replication)配置中,作為MASTER主服務器必須打開此項 # # # 如果你需要從你最後的備份中做基於時間點的恢復,你也同樣需要二進制日誌. # log-bin = mysql-bin #[必須]啟用二進制日誌 # # # 需要開啟生成二進制日誌記錄相關配置,配置在需要被復制的服務器上,即:master # binlog-do-db = test_db #指定對名稱為test_db的數據庫記錄二進制日誌 # binlog-ignore-db = mysql #指定不對名稱為mysql的數據庫記錄二進制日誌 # binlog-ignore-db = information_schema #指定不對名稱為information_schema的數據庫記錄二進制日誌 # binlog_format = mixed #binlog日誌格式,mysql默認采用,如果從服務器slave有別的slave要復制那麽該slave也需要這一項# expire_logs_days = 7 #超過7天的binlog刪除### # # # ##-------------------------------------------master上的配置開始-----------------------------------------------## ##-------------------------------------------slave上的配置開始------------------------------------------------## # # # # replicate-do-db 需要做復制的數據庫,如果復制多個數據庫,重復設置這選項即可master上不需要此項,slave上需要 # #replicate-do-db = test_db #復制名稱為test_db的數據庫 # # # replicate-ignore-db 不需要復制的數據庫,如果要忽略復制多個數據庫,重復設置這個選項即可 # #replicate-ignore-db = mysql #不需要(忽略)復制名稱為mysql的數據庫 # #replicate-ignore-db = information_schema #不需要(忽略)復制名稱為information_schema的數據庫 # # # # 如果你在使用鏈式從服務器結構的復制模式 (A->B->C), # # # 你需要在服務器B上打開此項. # # # 此選項打開在從線程上重做過的更新的日誌, # # # 並將其寫入從服務器的二進制日誌. # # # 默認值為OFF;設置log_slave_updates = 1即表示開啟 # #log_slave_updates = 1 # # # ##------------------------------------------slave上的配置結束-------------------------------------------------## skip-external-locking #MySQL選項以避免外部鎖定。該選項默認開啟 default-storage-engine = InnoDB #默認存儲引擎 lower_case_table_names = 1 #忽略表大小寫 ##------------------------------------------周建旭2017年3月6日 12:40:10添加------------------------------------#
截圖
註意:
binlog-do-db = 需要復制的數據庫名,如果復制多個數據庫,重復設置這個選項即可
binlog-ignore-db = 不需要復制的數據庫庫名,如果復制多個數據庫,重復設置這個選項即可
二.在192.168.42.129 上安裝MySQL(備庫)
創建用戶yingyue 授權可以遠程登錄和本地登錄,擁有該實例所有數據庫的權限。過程:略
配置slave服務器的my.cnf 文件 並重啟(配置slave對master的二進制文件復制)
##------------------------------------------周建旭2017年3月6日 12:40:10添加------------------------------------# # # server-id 唯一的服務辨識號,數值位於 1 到 2^32-1之間. # # 此值在master和slave上都需要設置. # # 如果 “master-host” 沒有被設置,則默認為1, 但是如果忽略此選項,MySQL不會作為master生效. server-id = 2 #[必須]服務器唯一ID,默認是1 ##------------------------------------------master上的配置開始------------------------------------------------## # # # # log-bin 打開二進制日誌功能. # # # 在復制(replication)配置中,作為MASTER主服務器必須打開此項 # # # 如果你需要從你最後的備份中做基於時間點的恢復,你也同樣需要二進制日誌. # #log-bin = mysql-bin #[必須]啟用二進制日誌 # # # 需要開啟生成二進制日誌記錄相關配置,配置在需要被復制的服務器上,即:master # #binlog-do-db = test_db #指定對名稱為test_db的數據庫記錄二進制日誌 # #binlog-ignore-db = mysql #指定不對名稱為mysql的數據庫記錄二進制日誌 # #binlog-ignore-db = information_schema #指定不對名稱為information_schema的數據庫記錄二進制日誌 # #binlog_format = mixed #binlog日誌格式,mysql默認采用,如果從服務器slave有別的slave要復制那麽該slave也需要該項 # #expire_logs_days = 7 #超過7天的binlog刪除### # # # ##-------------------------------------------master上的配置開始-----------------------------------------------## ##-------------------------------------------slave上的配置開始------------------------------------------------## # # # # replicate-do-db 需要做復制的數據庫,如果復制多個數據庫,重復設置這選項即可master上不需要此項,slave上需要 # replicate-do-db = test_db #復制名稱為test_db的數據庫 # # # replicate-ignore-db 不需要復制的數據庫,如果要忽略復制多個數據庫,重復設置這個選項即可 # replicate-ignore-db = mysql #不需要(忽略)復制名稱為mysql的數據庫 # replicate-ignore-db = information_schema #不需要(忽略)復制名稱為information_schema的數據庫 # # # # 如果你在使用鏈式從服務器結構的復制模式 (A->B->C), # # # 你需要在服務器B上打開此項. # # # 此選項打開在從線程上重做過的更新的日誌, # # # 並將其寫入從服務器的二進制日誌. # # # 默認值為OFF;設置log_slave_updates = 1即表示開啟 # #log_slave_updates = 1 # # # ##------------------------------------------slave上的配置結束-------------------------------------------------## skip-external-locking #MySQL選項以避免外部鎖定。該選項默認開啟 default-storage-engine = InnoDB #默認存儲引擎 lower_case_table_names = 1 #忽略表大小寫 ###------------------------------------------周建旭2017年3月6日 12:40:10添加------------------------------------#
截圖
註意:
replicate-do-db = 需要復制的數據庫名,如果復制多個數據庫,重復設置這個選項即可
replicate-ignore-db = 不需要復制的數據庫名,如果復制多個數據庫,重復設置這個選項即可
三.連接(我使用的是sqlyog)192.168.42.128服務器上的MySQL(主)
show master status; /*!查看主master的狀態,如果沒有數據,需要在my.cnf 中配置*/
註意:show master status; 只有在my.cnf中配置了log-bin開啟生成數據庫二進制記錄才會顯示數據
grant replication slave on *.* to ‘yingyue‘@‘%‘; /*!給ip地址為所有(%表示任何ip)MySQL服務器上的 盈月 授權對該master的復制權限*/
flush privileges; /*!刷新權限*/
四.連接 (我使用的是sqlyog)192.168.42.129 服務器上的MySQL(從)
show slave status; /*!查看該slave的狀態,只有該slave執行命令start slave; 後才有顯示記錄*/
停止從服務器
stop slave;
重置從服務器
reset slave;
從服務器關聯到主服務器
change master to master_user=‘root‘, master_password=‘a19911008‘, master_host=‘192.168.42.128‘,master_port=3306, master_log_file=‘mysql-bin.000002‘,master_log_pos=519;
註意:上面的關聯配置的信息都是主服務器上的,但是要在slave從服務器上配置,如果master_log_file和master_log_pos不知道可以在master服務器(192。168.42.128)上使用show master status;查看
執行成功!
開啟從服務器start slave;
查看從服務器連接狀態show slave status\G /*!不加分號*/
Sqlyog不支持\解析不了sql可以使用命令行來查看
使用賬號:yingyue 進行遠程登錄到192.168.42.129 上
全部信息如下:
Microsoft Windows [版本 6.1.7601] 版權所有 (c) 2009 Microsoft Corporation。保留所有權利。 C:\Users\Administrator>mysql -h192.168.42.129 -uyingyue -p000000 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 20 Server version: 5.7.17-log Source distribution Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the buffer. mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.42.128 Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 519 Relay_Log_File: localhost-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: test_db Replicate_Ignore_DB: 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: 519 Relay_Log_Space: 531 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 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: a70b33cb-ff4a-11e6-9fdc-000c29589bdd Master_Info_File: /usr/local/mysql-5.7.17/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: row in set (0.00 sec) mysql>
是否成功就看
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
是否都為Yes
如果有出現以上結果,則配置成功!
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
表示:從服務器已經讀到了所有的主服務器庫的二進制日誌,隨時待命復制;
下面來測試一下主從復制
測試描述:
DDL語句測試
在服務器192.168.42.128 的 test_db庫中新建 country表,看看從服務器192.168.42.129的test_db中是否會自動同步復制country表,如果可以,則表明主從復制成功;
執行 create table country(id int not null primary key auto_increment, name varchar(100));
看看從服務器192.168.42.129 上從庫test_db是否會自動同步country表
沒問題
下面來刪除主192.68.42.128上主庫test_db的country表
看看192.168.42.129 上的從庫的情況
也是可以的,沒問題,現在再重新創建表country 下面測試需要使用(在主庫中創建)
DML語句測試(包括insert, delete,update)
在192.168.42.128的主庫test_db上執行insert into country values(1, ‘南非‘),(2,‘瑞典‘),(3,‘哥斯達黎加‘),(4,‘新西蘭‘),(5,‘中國‘),(6,‘希臘‘) ,(7,‘意大利‘),(8,‘蘇格蘭‘) ,(9,‘冰島‘) ,(10,‘委內瑞拉‘) ,(11,‘比利時‘);
查看192.168.42.129的test_db從庫的country表是否多了11條記錄
沒問題。
在192.168.42.128的主庫test_db上執行update country set name=‘中華人民共和國‘ where id = 5;
查看192.168.42.129的test_db從庫的country表
沒問題。
在192.168.42.128的主庫test_db上執行 delete from country where id = 11;
查看192.168.42.129的test_db從庫的country表,最後一個 ‘比利時’應該沒了
沒問題。
讀寫分離(主庫寫, 從庫讀)
讀寫分離使用的中間件為mycat
安裝mycat 過程略
官方參考文檔:
配置mycat環境變量 略:
註意防火墻開啟8066 和9066 端口
修改server.xml文件
編輯server.xml文件(讀寫分離這些就夠了,多了礙眼)
<?xml version="1.0" encoding="UTF-8"?> <!-- - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --> <!DOCTYPE mycat:server SYSTEM "server.dtd"> <mycat:server xmlns:mycat="http://io.mycat/"> <system> <property name="useSqlStat">1</property> <!-- 1為開啟實時統計、0為關閉 --> </system> <user name="root"> <property name="password">a19911008</property> <property name="schemas">TESTDB</property> </user> <user name="yingyue"> <property name="password">000000</property> <property name="schemas">TESTDB</property> </user> </mycat:server>
配置schema.xml文件 vi conf/schema.xml
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema> <dataNode name="dn1" dataHost="localhost1" database="test_db" /> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="hostM1" url="192.168.42.128:3306" user="root" password="a19911008"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.42.129:3306" user="yingyue" password="000000" /> </writeHost> </dataHost> </mycat:schema>
啟動mycat 進入mycat安裝怒目執行/bin/mycat start 或 /bin/mycat console
如下啟動完成
使用mycat作為代理連接MySQL數據庫
yingyue是192.168.42.129上的MySQL用戶為什麽可以連接到192.168.42.128的MySQL呢?因為在剛才的mycat的server.xml中配置了,相當於代理
參數解釋
C:\Users\Administrator>mysql -h192.168.42.128 -uyingyue -p000000 -P8066 -DTESTDB
其中8066是mycat的監聽端口,類似於mysql的3306端口,其中-u,-p,-h分別是用戶名,密碼和主機,-P是mycat端口 -D是連接的邏輯庫。至於為什麽是這些,這個跟mycat的server.xml和schema.xml配置文件有關。
在命令行中執行explain select * from country;
看到數據是從dn1節點查的。
插入一條數據
下面來看看mycat監控日誌
從日誌看到最終被插入到192.168.42.128的MySQL的test_db的country中
看一下主庫是否有添加的數據
果然有,說明讀寫分離成功! 然後從庫192.168.42.129中的test_db會復制這條數據
沒問題的,讀寫分離也是成功的。
題外話:之前以為mycat可以實現主從庫數據復制,原來是不可以的,看看下面,其實mycat就是代理實現了主從庫的讀寫分離。總結:主從復制與讀寫分離無關,主從復制是MySQL的,讀寫分離是Mycat的。
--------------------------------------------------------------------------------------------------
高級篇
MySQL的slave斷了怎麽辦?
如下圖:
這個錯是我故意弄的,因為192.168.42.128上的test_db是很早前就建的庫並且裏面有account表,但是192.168.42.128上的MySQL我今天重啟過,每次重啟二進制日誌文件log-bin都不相同,在上次的文件版本上加一所以是mysql-bin.000002, 但是192.168.42.129服務器上的MySQL的是我今天重新關聯的,關聯的是mysql-bin.000002這個二進制日誌文件,這個文件中沒有記錄account表的創建和插入數據記錄。但是在我在主從復制正常的情況下在主服務器上將account刪掉,這時刪除的記錄會記錄到mysql-bin.000002的二進制日誌文件中,然後slave服務器的MySQL會復制master的日誌然後執行日誌,slave上的test_db沒有account表刪除肯定報錯;
解決方案:
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
解釋:
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1; 表示 跳過一個事物
查看從庫及其日誌,已經開始正常復制
說明:今天發現最後一步不用做,設置完set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;後,開啟slave後,該值自動變為0了。
------------------------------------------------------------------------------------------------------
延伸:
mysql主從錯誤斷開 怎樣恢復
mysql主從同步常見異常及恢復方法
1. 一般的異常只需要跳過一步即可恢復
mysql> stop slave;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> slave start;
2.斷電導致主從不能同步時,通主庫的最後一個bin-log日誌進行恢復
在主庫服務器上,mysqlbinlog mysql-bin.xxxx > binxxxx.txt
tail -n 100000 binxxxx.txt > tail-binxxxx.txt
vim tail-binxxxx.txt 打開tail-binxxxx.txt文件找到最後一個postion值
然後在從庫上,change host to 相應正確的值
mysql> stop slave;
mysql> change master to master_host=‘ip‘, master_user=‘username‘, master_password=‘password‘, master_log_file=‘mysql-bin.xxxx‘, master_log_pos=xxxx;
mysql> slave start;
mysql> show slave status\G
3.主鍵沖突、表已存在等錯誤代碼如1062,1032,1060等,可以在mysql主配置文件my.cnf或my.ini文件指定
略過此類異常並繼續下條sql同步,這樣也可以避免很多主從同步的異常中斷
[mysqld]
slave-skip-errors = 1062,1032,1060
-------------------------------------
從理想角度看,主從數據庫應該無故障的運轉下去,可以有時候還是會出現一些莫名其妙的問題,比如說即便從未在從服務器上手動更新過數據,但還是可能遇到“Error:
1062 Duplicate
entry”錯誤,具體原因不詳,可能是MySQL本身的問題。遇到這類問題的時候,從服務器會停止復制操作,我們只能手動解決問題,具體的操作步驟如下:
mysql> stop slave;
mysql> set global sql_slave_skip_counter = 1;
mysql> start slave;
同樣的操作可能需要進行多次,也可以設置自動處理此類操作,格式:slave-skip-errors = 錯誤代碼
在從服務器的my.cnf裏設置:
slave-skip-errors = 1062
MySQL主從復制 + Mycat實現讀寫分離