天天看點

MySQL(十四)之主從複制

一、MySQL複制概述

1、複制程序

   Mysql的複制(replication)是一個異步的複制,從一個Mysql instace(稱之為Master)複制到另一個Mysql instance(稱之Slave)。實作整個複制操作主要由三個程序完成的,其中兩個程序在Slave(SQL程序和IO程序),另外一個程序在 Master(IO程序)上。 要實施複制,首先必須打開Master端的binary log(bin-log)功能,否則無法實作。因為整個複制過程實際上就是Slave從Master端擷取該日志然後再在自己身上完全順序的執行日志中所記錄的各種操作。同時Slave還要開啟中繼日志,用來從Master同步二進制日志。

複制的基本過程如下:

  • Slave上面的IO程序連接配接上Master,并請求從指定日志檔案的指定位置(或者從最開始的日志)之後的日志内容; 
  • Master接收到來自Slave的IO程序的請求後,通過負責複制的IO程序根據請求資訊讀取制定日志指定位置之後的日志資訊,傳回給Slave 的IO程序。傳回資訊中除了日志所包含的資訊之外,還包括本次傳回的資訊已經到Master端的bin-log檔案的名稱以及bin-log的位置; 
  • Slave的IO程序接收到資訊後,将接收到的日志内容依次添加到Slave端的relay-log檔案的最末端,并将讀取到的Master端的 bin-log的檔案名和位置記錄到master-info檔案中,以便在下一次讀取的時候能夠清楚的高速Master“我需要從某個bin-log的哪個位置開始往後的日志内容,請發給我”; 
  • Slave的Sql程序檢測到relay-log中新增加了内容後,會馬上解析relay-log的内容成為在Master端真實執行時候的那些可執行的内容,并在自身執行。 

2、複制實作級别

   Mysql的複制可以是基于一條語句(Statement level),也可以是基于一條記錄(Row level),可以在Mysql的配置參數中設定這個複制級别,不同複制級别的設定會影響到Master端的bin-log記錄成不同的形式。

  • Row Level:日志中會記錄成每一行資料被修改的形式,然後在slave端再對相同的資料進行修改。

優點:在row level模式下,bin-log中可以不記錄執行的sql語句的上下文相關的資訊,僅僅隻需要記錄那一條記錄被修改了,修改成什麼樣了。是以row level的日志内容會非常清楚的記錄下每一行資料修改的細節,非常容易了解。而且不會出現某些特定情況下的存儲過程,或function,以及 trigger的調用和觸發無法被正确複制的問題。

缺點:row level下,所有的執行的語句當記錄到日志中的時候,都将以每行記錄的修改來記錄,這樣可能會産生大量的日志内容,比如有這樣一條update語句:update product set owner_member_id = ‘b’ where owner_member_id = ‘a’,執行之後,日志中記錄的不是這條update語句所對應額事件(mysql以事件的形式來記錄bin-log日志),而是這條語句所更新的每一條記錄的變化情況,這樣就記錄成很多條記錄被更新的很多個事件。自然,bin-log日志的量就會很大。尤其是當執行alter table之類的語句的時候,産生的日志量是驚人的。因為Mysql對于alter table之類的表結構變更語句的處理方式是整個表的每一條記錄都需要變動,實際上就是重建了整個表。那麼該表的每一條記錄都會被記錄到日志中。

  • Statement Level:每一條會修改資料的sql都會記錄到 master的bin-log中。slave在複制的時候sql程序會解析成和原來master端執行過的相同的sql來再次執行。

優點:statement level下的優點首先就是解決了row level下的缺點,不需要記錄每一行資料的變化,減少bin-log日志量,節約IO,提高性能。因為他隻需要記錄在Master上所執行的語句的細節,以及執行語句時候的上下文的資訊。

缺點:由于他是記錄的執行語句,是以,為了讓這些語句在slave端也能正确執行,那麼他還必須記錄每條語句在執行的時候的一些相關資訊,也就是上下文資訊,以保證所有語句在slave端杯執行的時候能夠得到和在master端執行時候相同的結果。另外就是,由于Mysql現在發展比較快,很多的新功能不斷的加入,使mysql得複制遇到了不小的挑戰,自然複制的時候涉及到越複雜的内容,bug也就越容易出現。在statement level下,目前已經發現的就有不少情況會造成mysql的複制出現問題,主要是修改資料的時候使用了某些特定的函數或者功能的時候會出現,比如:sleep()函數在有些版本中就不能真确複制,在存儲過程中使用了last_insert_id()函數,可能會使slave和master上得到不一緻的id等等。由于row level是基于每一行來記錄的變化,是以不會出現類似的問題。

  • Mixed:混合模式

   Mysql提供了除Statement Level和Row Level之外的第三種複制模式:Mixed,實際上就是前兩種模式的結合。在Mixed模式下,Mysql會根據執行的每一條具體的sql語句來區分對待記錄的日志形式,也就是在Statement和Row之間選擇一種。新版本中的Statment level還是和以前一樣,僅僅記錄執行的語句。而新版本的Mysql中隊row level模式也被做了優化,并不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄,如果sql語句确實就是update或者delete等修改資料的語句,那麼還是會記錄所有行的變更。

3、複制常用架構

  • 一主一從

   Mysql複制環境90%以上都是一個Master帶一個或者多個Slave的架構模式,主要用于讀壓力比較大的應用的資料庫端廉價擴充解決方案。因為隻要master和slave的壓力不是太大(尤其是slave端壓力)的話,異步複制的延時一般都很少很少。尤其是自slave端的複制方式改成兩個程序處理之後,更是減小了slave端的延時。而帶來的效益是,對于資料實時性要求不是特别的敏感度的應用,隻需要通過廉價的pc server來擴充slave的數量,将讀壓力分散到多台slave的機器上面,即可解決資料庫端的讀壓力瓶頸。這在很大程度上解決了目前很多中小型網站的資料庫壓力瓶頸問題,甚至有些大型網站也在使用類似方案解決資料庫瓶頸。

MySQL(十四)之主從複制
  • 一主多從

   一個Master帶多個slave的架構實施非常簡單,多個slave和單個slave的實施并沒有太大差別。在Master端并不care有多少個 slave連上了master端,隻要有slave程序通過了連接配接認證,向他請求binlog資訊,他就會按照連接配接上來的io程序的要求,讀取自己的 binlog資訊,傳回給slave的IO程序。對于slave的配置細節,在Mysql的官方文檔上面已經說的很清楚了,甚至介紹了多種實作slave 的配置方法。 

MySQL(十四)之主從複制

為減低主伺服器的複制壓力,還可以使用級聯複制的方式工作,下圖就是其工作原理:

MySQL(十四)之主從複制
  • 雙主模型

   Mysql也可以搭建成dual master模式,也就是說兩個Mysql instance互為對方的Master,也同時為對方的Slave。不過一般這種架構也是隻有一端提供服務,避免沖突問題。因為即使在兩邊執行的修改有先後順序,由于複制的異步實作機制,同樣會導緻即使在晚做的修改也可能會被早做的修改所覆寫,就像如下情形:

時間點 Mysql A Mysql B

1 更新x表y記錄為10

2 更新x表y記錄為20

3 擷取到A日志并應用,更新x表的y記錄為10(不符合期望)

4 擷取B日志更新x表y記錄為20(符合期望)

   這樣,不僅在B庫上面的資料不是使用者所期望的結果,A和B兩邊的資料也出現了不一緻的情況。除非能将寫操作根據某種條件固定分開在A和B兩端,保證不會交叉寫入,才能夠避免上面的問題。

MySQL(十四)之主從複制
  • 雙主帶從伺服器的Master-Master結構(Master-Master with Slaves) 

這種結構的優點就是提供了備援。在地理上分布的複制結構,它不存在單一節點故障問題,而且還可以将讀密集型的請求放到slave上。

MySQL(十四)之主從複制

二、一主一從環境配置

   實驗前關于資料庫版本的說明:雙方的MySQL要一緻,如果不一緻:主的要低于從的,同時兩台機器上的時間必須一緻。

主從伺服器資料的起始點:

  • 雙方都從0開始做主從複制,若資料量較小可以使用此類操作,若資料很大就用下面的方法。
  • 主伺服器已經運作一段時間,并且存在不小的資料集。方法是把主伺服器備份,然後在從服務恢複,從主伺服器上備份時所處的位置開始複制;

1、實驗環境

hostname IP 資料庫版本 Linux
master example.com 192.168.1.8 MariaDB-10.0.21 CentOS 6.6
slave Slave 192.168.1.9

2、從0開始做主從複制

主機器的實驗環境準備:

[[email protected] ~]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS! 
[[email protected] ~]# vim /etc/my.cnf
log-bin=/data/binlog/master-bin    //正常中一定要将檔案放在與資料檔案不同的實體裝置。
server-id       = 1
sync_binlog  = 1   //啟用一旦有事務送出時立即将緩沖區的内容同步到二進制日志。
[[email protected] ~]# mkdir /data/binlog
[[email protected] ~]# chown -R mysql.mysql /data/binlog
[[email protected] ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!      

我們還可以手動設定同步二進制日志,這樣做會損失一定的寫性能:

MariaDB [(none)]> set global sync_binlog=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show global variables like 'sync_binlog';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
1 row in set (0.00 sec)      

建議在設定前最好将自動送出的功能給關閉:

MariaDB [(none)]> set global autocommit=0;
Query OK, 0 rows affected (0.17 sec)

MariaDB [(none)]> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set (0.00 sec)      

從機器的實驗環境準備:

[root@Slave ~]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS! 
[root@Slave ~]# vim /etc/my.cnf 
#log-bin=mysql-bin    //一定要将從的二進制日志檔案取消
#binlog_format=mixed
server-id       = 2    //server-id一定不能和主的相同
relay_log       = /data/relaylog/relay-bin   //正常中一定要将檔案放在與資料檔案不同的實體裝置。
read_only         = 1   //限制從伺服器隻讀
[root@Slave ~]# mkdir /data/relaylog
[root@Slave ~]# chown -R mysql.mysql /data/relaylog
[root@Slave ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!      

設定從伺服器為隻讀的方法也可以使用在指令行手動配置:

MariaDB [(none)]> show global variables like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | OFF   |
+---------------+-------+
1 row in set (0.08 sec)

MariaDB [(none)]> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)      

注意:read_only僅能限制那不具有SUPER權限使用者無法執行寫操作;

主機器的資料庫授權等操作:

MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.1.9' IDENTIFIED BY 'redhat';     //建立有複制權限的帳号
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show processlist;
+----+------+-----------+------+---------+------+-------+------------------+---------
| Id | User | Host      | db   | Command | Time | State | Info             | Progress
+----+------+-----------+------+---------+------+-------+------------------+---------
|  4 | root | localhost | NULL | Query   |    0 | init  | show processlist |    0.000
+----+------+-----------+------+---------+------+-------+------------------+---------
1 row in set (0.00 sec)

MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |      639 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)      

從伺服器連接配接主伺服器:

MariaDB [(none)]> show global variables like '%relay%';   //檢視中繼日志是否啟用
+-----------------------+--------------------------+
| Variable_name         | Value                    |
+-----------------------+--------------------------+
| max_relay_log_size    | 1073741824               |
| relay_log             | /data/relaylog/relay-bin |
| relay_log_index       |                          |
| relay_log_info_file   | relay-log.info           |
| relay_log_purge       | ON                       |
| relay_log_recovery    | OFF                      |
| relay_log_space_limit | 0                        |
| sync_relay_log        | 0                        |
| sync_relay_log_info   | 0                        |
+-----------------------+--------------------------+
9 rows in set (0.01 sec)

MariaDB [(none)]> change master to master_host='192.168.1.8',master_user='repluser',master_password='redhat';  //連接配接主伺服器
Query OK, 0 rows affected (0.05 sec)

MariaDB [(none)]> start slave;   //啟動從伺服器
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show slave status\G;   //檢視是否啟動
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.8                  #Master伺服器位址
                  Master_User: repluser                       #連接配接Master伺服器使用者名
                  Master_Port: 3306                             #Master伺服器監聽端口
                Connect_Retry: 60                               #重試時間間隔
              Master_Log_File: master-bin.000001   #I/O線程讀取的二進制日志檔案
          Read_Master_Log_Pos: 639                      #I/O線程讀取的二進制日志檔案事件位置
               Relay_Log_File: relay-bin.000002        #SQL線程正在讀取的中繼日志檔案
                Relay_Log_Pos: 927                            #SQL線程讀取和執行的中繼日志檔案事件位置
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes                         #Slave伺服器IO線程狀态
            Slave_SQL_Running: Yes                        #Slave伺服器SQL線程狀态
              Replicate_Do_DB:                                #下面Replicate開頭的表示用來指明哪些庫或者表在複制時不需要同步
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0                                    #SQL線程讀取日志參數的錯誤數量
                   Last_Error:                                        #SQL線程讀取日志參數的錯誤消息
                 Skip_Counter: 0                                #最近被用于SQL_SLAVE_SKIP_COUNTER的值
          Exec_Master_Log_Pos: 639
              Relay_Log_Space: 1218                        #所有原有中繼日志的總大小
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No                    #是否允許對Master伺服器進行SSL連接配接
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0                    #落後于Master伺服器的時間
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_SSL_Crl:
           Master_SSL_Crlpath:
                   Using_Gtid: No
                  Gtid_IO_Pos:
1 row in set (0.00 sec)      

驗證是否能夠達到主從複制:

檢視從伺服器的線程。

MariaDB [testdb]> show processlist;
+----+----------+-------------------+--------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
| Id | User     | Host              | db     | Command     | Time | State                                                                 | Info             | Progress |
+----+----------+-------------------+--------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
|  4 | root     | localhost         | testdb | Query       |    0 | init                                                                  | show processlist |    0.000 |
|  5 | repluser | 192.168.1.9:50797 | NULL   | Binlog Dump | 1253 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL             |    0.000 |
+----+----------+-------------------+--------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
2 rows in set (0.00 sec)      

在主伺服器上建立資料。

MariaDB [(none)]> create database testdb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> show databases;
+---------------------+
| Database            |
+---------------------+
| #mysql50#lost+found |
| information_schema  |
| mysql               |
| performance_schema  |
| test                |
| testdb              |
+---------------------+
6 rows in set (0.01 sec)

MariaDB [(none)]> use testdb
Database changed

MariaDB [testdb]> create table tt(name char(30));
Query OK, 0 rows affected (0.05 sec)

MariaDB [testdb]> insert into tt values ('bols');
Query OK, 1 row affected (0.01 sec)      

從伺服器檢視主從是否同步:

MariaDB [(none)]> show databases;
+---------------------+
| Database            |
+---------------------+
| #mysql50#lost+found |
| information_schema  |
| mysql               |
| performance_schema  |
| test                |
| testdb              |
+---------------------+
6 rows in set (0.00 sec)

MariaDB [(none)]> use testdb
Database changed

MariaDB [testdb]> select * from tt;
+------+
| name |
+------+
| bols |
+------+
1 row in set (0.00 sec)      

3、半路複制

環境的搭建和前面的 一樣就不介紹了,下面就關于兩者不同的地方做下示範,下面添加新的資料。:

MariaDB [(none)]> create database testdb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> use testdb
Database changed

MariaDB [testdb]> create table tt(name char(20));
Query OK, 0 rows affected (0.11 sec)

MariaDB [testdb]> insert into tt values('bols'),('longls');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0      

備份資料并傳送到從伺服器上:

[[email protected] ~]# mysqldump -uroot -hlocalhost -p --all-databases --flush-logs --master-data=2 --lock-all-tables > /tmp/all.sql
Enter password: 
[[email protected] ~]# scp /tmp/all.sql [email protected]:/root
導入資料:
[root@Slave ~]# mysql < all.sql 
[root@Slave ~]# head -30 all.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=367;

MariaDB [mysql]> show slave status\G;   //一定要将從伺服器的服務給關閉了。
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 192.168.1.8
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 1057
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 1345
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No
MariaDB [mysql]> change master to master_host='192.168.1.8',master_user='repluser',master_password='redhat',master_log_file='master-bin.000002',master_log_pos=367;
Query OK, 0 rows affected (0.04 sec)

MariaDB [mysql]> start slave;
Query OK, 0 rows affected (0.00 sec)      

檢視資訊是否同步:

MariaDB [hellodb]>  select * from testdb.tt;
+--------+
| name   |
+--------+
| bols   |
| longls |
+--------+
2 rows in set (0.00 sec)      

三、基于半同步方式工作的一主多從架構

   前面我們已經說到了,在使用主從架構時為了提高性能故其是基于異步通信方式進行工作的,這種方式工作有種緻命缺陷就是有有長時間的工作,從伺服器上的資料和主伺服器上的資料極有可能不一緻,我們可以使用一些工具進行強行同步資料,也可以手動同步資料,下面介紹一個有谷歌提供的能讓其能基于半同步狀态工作的插件。semi-synchronously,這種插件隻能工作唉MySQL5.5版本以上的資料庫。而實際工作中若一旦某次等待逾時,會自動降級為異步;

檢視資料庫是否支援半同步:

[[email protected] ~]# ls /usr/local/mysql/lib/plugin/semisync_*
/usr/local/mysql/lib/plugin/semisync_master.so
/usr/local/mysql/lib/plugin/semisync_slave.so      

主伺服器上安裝master插件:

MariaDB [(none)]> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.09 sec)

MariaDB [(none)]> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> set global rpl_semi_sync_master_timeout=2000;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | ON    |
| rpl_semi_sync_master_timeout       | 2000  |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
4 rows in set (0.00 sec)      

rpl_semi_sync_master_enabled:主節點是否啟動

rpl_semi_sync_master_timeout:等待逾時時間,機關ms

從服務安裝插件:

MariaDB [(none)]>  install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.08 sec)

MariaDB [(none)]> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

MariaDB [(none)]> stop slave io_thread;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)      

測試半同步是否工作:

MariaDB [testdb]> create table t1(name char(20));
Query OK, 0 rows affected (0.12 sec)

MariaDB [testdb]> create table t2(name char(20));
Query OK, 0 rows affected (0.04 sec)

MariaDB [testdb]> show global status like '%semi%';  //第一項為1說明已工作
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 390   |
| Rpl_semi_sync_master_net_wait_time         | 781   |
| Rpl_semi_sync_master_net_waits             | 2     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 324   |
| Rpl_semi_sync_master_tx_wait_time          | 648   |
| Rpl_semi_sync_master_tx_waits              | 2     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)      

四、主從複制的複制過濾器

   在使用複制過濾器時雖然在主上設定會有好的性能,但是其有一個緻命缺陷就是造成資料的缺失,而一般使用還是在從伺服器上設定,雖然有一定的性能損失,但是資料得到可保障。

1、主上參數設定

  • binlog_do_db=     //資料庫白名單
  • binlog_ignore_db=    //資料庫黑名單

2、從上參數設定

  • replicate_do_db=    //資料庫白名單
  • replicate_ignore_db=   //資料庫黑名單
  • replicate_do_table= db_name.table_name    //表的白名單
  • replicate_ignore_table=db_name.table_name    //表的黑名單
  • replicate_wild_do_table=      //基于通配符來指定表的白名單
  • replicate_wild_ignore_table=   //基于通配符來指定表的黑名單

五、雙主模型

在IP為192.168.1.8的主機做以下配置:

[[email protected] ~]# /etc/init.d/mysqld stop
Shutting down MySQL... SUCCESS!
[[email protected] ~]# vim /etc/my.cnf
log-bin=/data/binlog/master-bin
binlog_format=mixed
relay_log = /data/relaylog/relay-bin
auto-increment-offset = 1    //起始值
auto-increment-increment = 2   //步長
skip_slave_start    //跳過自動啟動slave,進而手動啟動slave
[[email protected] ~]# mkdir /data/relaylog
[[email protected] ~]# chown -R mysql.mysql /data/relaylog
[[email protected] ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!      

IP為192.168.1.9的主機做以下設定:

[root@Slave ~]# /etc/init.d/mysqld stop
Shutting down MySQL... SUCCESS! 
[root@Slave ~]# vim /etc/my.cnf
log-bin=/data/binlog/master-bin
binlog_format=mixed
server-id       = 2
auto-increment-offset = 2  
auto-increment-increment = 2
relay_log       = /data/relaylog/relay-bin
skip_slave_start
[root@Slave ~]# mkdir /data/binlog
[root@Slave ~]# chown -R mysql.mysql /data/binlog
[root@Slave ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!      

登入192.168.1.8的mysql做以下設定:

MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000004 |      327 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> select User,Host,Password from mysql.user;
+----------+-------------+-------------------------------------------+
| User     | Host        | Password                                  |
+----------+-------------+-------------------------------------------+
| root     | localhost   | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | example.com | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | 127.0.0.1   | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | ::1         | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| repluser | 192.168.1.9 | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
+----------+-------------+-------------------------------------------+
5 rows in set (0.00 sec)

MariaDB [(none)]> change master to master_host='192.168.1.9',master_user='repluser',master_password='redhat',master_log_file='master-bin.000001',master_log_pos=649;
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.08 sec)

MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.9
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 649
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 536
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes      
MariaDB [(none)]>  grant replication slave,replication client on *.* to 'repluser'@'192.168.1.8' identified by 'redhat';
Query OK, 0 rows affected (0.11 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> select User,Host,Password from mysql.user;
+----------+-------------+-------------------------------------------+
| User     | Host        | Password                                  |
+----------+-------------+-------------------------------------------+
| root     | localhost   | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | example.com | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | 127.0.0.1   | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| root     | ::1         | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
| repluser | 192.168.1.8 | *84BB5DF4823DA319BBF86C99624479A198E6EEE9 |
+----------+-------------+-------------------------------------------+
6 rows in set (0.00 sec)

MariaDB [(none)]> change master to master_host='192.168.1.8',master_user='repluser',master_password='redhat',master_log_file='master-bin.000004',master_log_pos=327;
Query OK, 0 rows affected (0.12 sec)

MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |      649 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.8
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000004
          Read_Master_Log_Pos: 327
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 536
        Relay_Master_Log_File: master-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes      

驗證是否同步:

192.168.1.8的伺服器做以下操作:

MariaDB [newdb]> create table tt(id int unsigned not null primary key auto_increment,name char(20));
Query OK, 0 rows affected (0.09 sec)

MariaDB [newdb]> insert into tt(name) values('longls'),('bols');
Query OK, 2 rows affected (0.13 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [newdb]> select * from tt;
+----+--------+
| id | name   |
+----+--------+
|  1 | longls |
|  3 | bols   |
+----+--------+
2 rows in set (0.00 sec)      

192.168.1.9的伺服器做以下操作:

MariaDB [newdb]> insert into tt(name) values('xiaozels'),('cangls');
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [newdb]> select * from tt;
+----+----------+
| id | name     |
+----+----------+
|  1 | longls   |
|  3 | bols     |
|  4 | xiaozels |
|  6 | cangls   |
+----+----------+
4 rows in set (0.07 sec)      

六、知識點

1、複制相關的檔案:

  master.info: 文本檔案,儲存從伺服器連接配接至主服務時所需要的資訊,每行一個值;

  relay-log.info: 文本檔案,儲存了複制位置:包括二進制日志和中繼日志的檔案及位置;

2、為了複制的安全性可以做以下操作,但是會損失一定的性能

   sync_master_info = 1    

   sync_relay_log = 1  

   sync_relay_log_info = 1

3、percona-toolkit工具

   這是有percona提供的一款工具包,能執行很多指令,其中當從伺服器意外崩潰時,建議使用pt-slave-start指令來啟動slave。

評估主從服務表中的資料是否一緻:pt-table-checksum。

4、如果資料不一緻,解決辦法

  • 重新備份并在從伺服器導入資料;
  • 使用pt-table-sync工具同步資料

5、為了提高複制時的資料安全性,在主伺服器上的設定

   sync_binlog = 1

   innodb_flush_log_at_trx_commit = 1

   此參數的值設定為1,性能下降會較嚴重;是以,一般設定為2等,此時,主伺服器崩潰依然有可能導緻從伺服器無法擷取到全部的二進制日志事件;

6、如果master意外崩潰導緻二進制日志中的某事件損壞,可以在從伺服器使用如下參數忽略:

   sql_slave_skip_counter = 0