1. 程式人生 > 其它 >MySQL(三)MySQL-5.7.20 主從複製實戰(半同步複製、過濾複製、GTID模式)

MySQL(三)MySQL-5.7.20 主從複製實戰(半同步複製、過濾複製、GTID模式)

技術標籤:資料庫&訊息佇列資料庫mysql

MySQL-5.7.20二進位制主從複製實戰(半同步複製、過濾複製、GTID模式)

文章目錄

一、半同步複製

半同步複製的原理

半同步複製時,為了保證主庫上的每一個Binlog事務都能夠被可靠的複製到從庫上,主庫在每次事務成功提交時,並不及時反饋給前端應用使用者,而是等待其中的一個從庫也接收到Binlog事務併成功寫入中繼日誌後,出庫才返回commit操作成功給客戶端。半同步複製保證了事務成功提交後,至少有兩份日誌記錄,一份在主庫的Binlog日誌上,另一份在至少一個從庫的中繼日誌Relay log上,從而更近一步保證了資料的完整性。

img

半同步複製先決條件

前文已經有二進位制多例項主從複製的文件,本文件不再從新開啟主從複製,如果沒有開啟請點選:二進位制主從複製

在做半同步複製前請保證開啟了主從同步

半同步複製實戰

載入sync外掛

[mark_d]注意:主庫與從庫載入的外掛不是同一個!!![/mark_d]

[[email protected] ~]# mysql -S /opstands/mysql-3307/mysql.sock -e "install plugin rpl_semi_sync_master soname 'semisync_master.so';"
[[email protected]
~]# mysql -S /opstands/mysql-3308/mysql.sock -e "install plugin rpl_semi_sync_slave soname 'semisync_slave.so';"

檢視外掛

[[email protected] ~]# mysql -S /opstands/mysql-3307/mysql.sock -e "show plugins" |grep rpl_semi_sync
rpl_semi_sync_master	ACTIVE	REPLICATION	semisync_master.so	GPL
[[email protected] ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "show plugins" |grep rpl_semi_sync
rpl_semi_sync_slave	ACTIVE	REPLICATION	semisync_slave.so	GPL

啟動半同步

注意: 外掛名稱不一樣

[[email protected] ~]# mysql -S /opstands/mysql-3307/mysql.sock -e "set global rpl_semi_sync_master_enabled = 1;"

[[email protected] ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "set global rpl_semi_sync_slave_enabled= 1 ;"

重啟從庫IO執行緒

[[email protected] ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "stop slave io_thread;"
[[email protected] ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "start slave io_thread;"

檢視是否執行

[root@mysql-manager ~]# mysql -S /opstands/mysql-3307/mysql.sock -e "show status like 'Rpl_semi_sync_master_status';"
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON    |
+-----------------------------+-------+

[root@mysql-manager ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "show status like 'Rpl_semi_sync_slave_status';"
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+

二、過濾複製

複製的過濾主要有2種方式

  1. 在主伺服器在把事件從進二制日誌中過濾掉,相關的引數是:binlog_do_db和binlog_ignore_db。
  2. 在從伺服器上把事件從中繼日誌中過濾掉,相關的引數是replicate_*。
  • 複製只能擴充套件讀取,不能擴充套件寫入,對資料進行分割槽可以進行擴充套件寫入。

複製的優化:

在mysql複製環境中,有8個引數可以讓我們控制,需要複製或需要忽略不進行復制的DB或table。

下面二項需要在Master上設定:

  1. Binlog_Do_DB:設定哪些資料庫需要記錄Binlog
  2. Binlog_Ignore_DB:設定哪裡資料庫不需要記錄Binlog
  • 優點是Master端的Binlog記錄所帶來的Io量減少,網路IO減少,還會讓slave端的IO執行緒,SQL執行緒減少,從而大幅提高複製效能,
  • 缺點是mysql判斷是否需要複製某個事件不是根據產生該事件的查詢所在的DB,而是根據執行查詢時刻所在的預設資料庫(也就是登入時指定的庫名或執行”use database”中指定的DB),只有當前預設DB和配置中所設定的DB完全吻合時IO執行緒才會將該事件讀取給slave的IO執行緒.所以,如果在預設DB和設定須要複製的DB不一樣的情況下改變了須要複製的DB中某個Table中的資料,該事件是不會被複制到Slave中去的,這樣就會造成Slave端的資料和Master的資料不一致.同樣,在預設的資料庫下更改了不須要複製的資料庫中的資料,則會被複制到slave端,當slave端並沒有該資料庫時,則會造成複製出錯而停止。

下面六項需要在slave上設定:

  1. Replicate_Do_DB:設定需要複製的資料庫,多個DB用逗號分隔
  2. Replicate_Ignore_DB:設定可以忽略的資料庫.
  3. Replicate_Do_Table:設定需要複製的Table
  4. Replicate_Ignore_Table:設定可以忽略的Table
  5. Replicate_Wild_Do_Table:功能同Replicate_Do_Table,但可以帶萬用字元來進行設定。
  6. Replicate_Wild_Ignore_Table:功能同Replicate_Do_Table,功能同Replicate_Ignore_Table,可以帶萬用字元。
  • 優點是在slave端設定複製過濾機制,可以保證不會出現因為預設的資料庫問題而造成Slave和Master資料不一致或複製出錯的問題.
  • 缺點是效能方面比在Master端差一些.原因在於:不管是否須要複製,事件都會被IO執行緒讀取到Slave端,這樣不僅增加了網路IO量,也給Slave端的IO執行緒增加了Relay Log的寫入量。

主從過濾的注意事項:

  • 使用replicate_do_db和replicate_ignore_db時有一個隱患,跨庫更新時會出錯。
  • 如在Master(主)伺服器上設定 replicate_do_db=test(my.conf中設定)

主從複製過濾複製先決條件

前文已經有二進位制多例項主從複製的文件,本文件不再從新開啟主從複製,如果沒有開啟請點選:二進位制主從複製

在做過濾複製前請保證開啟了主從同步

主從複製過濾複製實戰

新增配置檔案白名單引數

[[email protected] ~]# echo 'replicate_do_db=olda' >> /opstands/mysql-3308/my.cnf

# -----------------------------------------------------
# replicate_ignore_db是黑名單,用法和白名單一樣

重啟3308例項

[[email protected] ~]# systemctl restart mysqld-3308.service

檢視過濾複製的資訊

[[email protected] ~]# mysql -S /opstands/mysql-3308/mysql.sock -e "show slave status\G" |egrep 'Replicate_Do_DB:|Replicate_Ignore_DB:'
              Replicate_Do_DB: olda
          Replicate_Ignore_DB:

現在主從複製只會同步olda庫的資料

三、GTID模式

GTID優勢

  • 更簡單的實現 failover,不用以前那樣在需要找 log_file 和 log_Pos。
  • 更簡單的搭建主從複製。
  • 複製叢集有一個統一的方式識別複製位置,給叢集管理帶來了便利。
  • 正常情況下,GTID 是連續沒有空洞的,因此主從庫出現數據衝突時,可以用新增空事物的方式進行跳過。

GTID的限制

  1. 在一個事務裡面混合使用引擎,如 Innodb(支援事務)、MyISAM(不支援事務), 造成多個 GTIDs 和同一個事務相關聯出錯
  2. CREATE TABLE……SELECT 不能使用,該語句產生的兩個 event 在某一情況 會使用同一個 GTID(同一個 GTID 在 slave 只能被使用一次)
    1th event:建立表語句 create table
    2th event:插入資料語句 insert
  3. CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE 不能在事務內使用 (啟用了–enforce-gtid-consistency 引數)。

GTID的工作原理

1、master更新資料時,會在事務前產生GTID,一同記錄到binlog日誌中。

2、slave端的i/o 執行緒將變更的binlog,寫入到本地的relay log中。

3、sql執行緒從relay log中獲取GTID,然後對比slave端的binlog是否有記錄。

4、如果有記錄,說明該GTID的事務已經執行,slave會忽略。

5、如果沒有記錄,slave就會從relay log中執行該GTID的事務,並記錄到binlog。

6、在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果沒有就用全部掃描。

  • server_uuid是MySQL Server的只讀變數,儲存在資料目錄下的auto.cnf中,可直接通過cat命令檢視。MySQL第一次啟動時候建立auto.cnf檔案,並生成server_uuid(MySQL使用機器網絡卡,當前時間,隨機數等拼接成一個128bit的uuid,可認為在全宇宙都是唯一的,在未來一百年,使用同樣的演算法生成的uuid是不會衝突的)。之後MySQL再啟動時不會重複生成uuid,而是使用auto.cnf中的uuid。
  • 在同一個叢集內,每個MySQL例項的server_uuid必須唯一,否則同步時,會造成IO執行緒不停的中斷,重連。在通過備份恢復資料時,一定要將var目錄中的auto.cnf刪掉,讓MySQL啟動時自己生成uuid
  • GTID中還有一部分是transaction_id,同一個server_uuid下的transaction_id一般是遞增的。如果一個事務是通過使用者執行緒執行,那麼MySQL在生成的GTID時,會使用它自己的server_uuid,然後再遞增一個transaction_id作為該事務的GTID。當然,如果事務是通過SQL執行緒回放relay-log時產生,那麼GTID就直接使用binlog裡的了。在MySQL 5.6中不用擔心binlog裡沒有GTID,因為如果從庫開啟了GTID模式,主庫也必須開啟,否則IO執行緒在建立連線的時候就中斷了。5.6的GTID對MySQL的叢集環境要求是非常嚴格的,要麼主從全部開啟GTID模式,要麼全部關閉GTID模式。
  • 使用server_uuid:transaction_id共同組成一個GTID的好處是,由於server_uuid唯一,即使一個叢集內多個節點同時有寫入,也不會造成GTID衝突。

GTID的使用

  • MySQL通過全域性變數gtid_mode控制開啟/關閉GTID模式。但是gtid_mode是隻讀的,可新增到配置檔案中,然後重啟mysqld來開啟GTID模式。

GTID原理

  • 我們知道,在未開啟GTID模式的情況下,從庫用(File_name和File_pos)二元組標識執行到的位置。START SLAVE時,從庫會先向主庫傳送一個BINLOG_DUMP命令,在BINLOG_DUMP命令中指定File_name和File_pos,主庫就從這個位置開始傳送binlog。
  • 在開啟GTID模式的情況下,如果指定MASTER_AUTO_POSITION=1。START SLAVE時,從庫會計算Retrieved_Gtid_Set和Executed_Gtid_Set的並集(通過SHOW SLAVE STATUS可以檢視),然後把這個GTID並集傳送給主庫。主庫會使用從庫請求的GTID集合和自己的gtid_executed比較,把從庫GTID集合裡缺失的事務全都發送給從庫。如果從庫缺失的GTID,已經被主庫pruge了呢?從庫報1236錯誤,IO執行緒中斷。
  • 通過GTID找到點兒的原理還是比較奇怪的,它過於強調主從binlog中GTID集合的一致性,弱化了Binlog執行的順序性。

img

pos 與 GTID 有什麼區別?

  • 兩者都是日誌檔案裡事件的一個標誌,如果將整個 mysql 叢集看作一個整體,pos就是區域性的,GTID就是全域性的.
  • 一主兩從,在 master,slave1,slave2 日誌檔案裡的 pos,都各不相同,就是一個 event,在 master 的日誌裡,pos 可能是 700,而在 slave1,slave2 裡,pos 可能就是 300,400 了,因為眾多 slave 也可能不是同時加入叢集的,不是從同一個位置進行同步.
  • 而 GTID,在 master,slave1,slave2 各自的日誌檔案裡,同一個 event 的 GTID 值都是一樣的.

GTID模式主從複製先決條件

前文已經有二進位制多例項安裝的文件,本文件不再從新安裝,如果沒有安裝請點選:二進位制多例項安裝

[[email protected] ~]# mkdir -p /opstands/mysql-5.7.20/binlog

GTID模式主從複製實戰

本文將使用MySQL-3306例項為主節點,MySQL3309例項為從節點。

開啟binlog日誌與GTID

[[email protected] ~]# sed -i '7a log_bin=/opstands/mysql-5.7.20/binlog/mysql-bin' /etc/my.cnf
[[email protected] ~]# sed -i '8a binlog_format=row' /etc/my.cnf
[[email protected] ~]# sed -i '9a sync_binlog=1' /etc/my.cnf
[[email protected] ~]# sed -i '10a gtid_mode=ON' /etc/my.cnf
[[email protected] ~]# sed -i '11a enforce_gtid_consistency' /etc/my.cnf
[[email protected] ~]# cat >> /opstands/mysql-3309/my.cnf <<EOF
gtid_mode=ON
enforce_gtid_consistency
EOF

授權

[[email protected] ~]# chown -R mysql.mysql /opstands/mysql-*

重啟3306與3309例項

[[email protected] ~]# systemctl restart mysqld.service
[[email protected] ~]# systemctl restart mysqld-3309.service

檢視是否開啟GTID

[root@mysql-manager ~]# mysql -uroot -predhat -e "show variables like '%gtid_%';"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |       <------- 是否開啟GTID
| gtid_executed_compression_period | 1000      |
| gtid_mode                        | ON        |               <-------是否啟用GTID模組
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
[root@mysql-manager ~]# mysql -S /opstands/mysql-3309/mysql.sock -e "show variables like '%gtid_%';"
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |       <------- 是否開啟GTID
| gtid_executed_compression_period | 1000      |
| gtid_mode                        | ON        |               <-------是否啟用GTID模組
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+

建立主從複製使用者

[[email protected] ~]# mysql -uroot -predhat -e "grant replication slave on *.* to [email protected]'%' identified by 'redhat';"

開啟GTID主從複製

# 進入3309例項資料庫內開啟GTID連線到3306例項
[root@mysql-manager ~]# mysql -S /opstands/mysql-3309/mysql.sock
mysql> CHANGE MASTER TO
    ->    MASTER_HOST='172.18.1.79',
    ->    MASTER_USER='rep',
    ->    MASTER_PASSWORD='redhat',
    ->    MASTER_PORT=3306,
    ->    MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

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

檢視主從複製狀態

[root@mysql-manager mysql-3309]# mysql -S /opstands/mysql-3309/mysql.sock -e "show slave status\G;" |egrep 'Slave_IO_Running:|Slave_SQL_Running:|Seconds_Behind_Master:'
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
        Seconds_Behind_Master: 0

測試GTID模式主從複製效果

可以看到當前兩個例項都沒有olda庫,接下來在3306庫建立olda庫,然後檢視3309庫是否有同步。

[root@mysql-manager ~]# mysql -uroot -predhat -e "show databases;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
[root@mysql-manager mysql-3309]# mysql -S /opstands/mysql-3309/mysql.sock -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

檢視結果

可以看到3309例項從庫也同步建立了olda庫

[root@mysql-manager ~]# mysql -uroot -predhat -e "create database olda charset utf8mb4;"
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@mysql-manager ~]# mysql -uroot -predhat -e "show databases;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| olda               |
| performance_schema |
| sys                |
+--------------------+
[root@mysql-manager mysql-3309]# mysql -S /opstands/mysql-3309/mysql.sock -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| olda               |
| performance_schema |
| sys                |
+--------------------+
sys                |
+--------------------+
[root@mysql-manager mysql-3309]# mysql -S /opstands/mysql-3309/mysql.sock -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| olda               |
| performance_schema |
| sys                |
+--------------------+