1. 程式人生 > >MySQL主從複製 + Mycat實現讀寫分離

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.xmlschema.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