把嘴給我閉上!我說個數,五分鐘!搞懂 MySQL主從複製原理

推薦閱讀:

MySQL 主從複製主流架構模型

我們基於 Binlog 可以複製出一臺 MySQL 服務器,也可以複製出多臺,取決於我們想實現什麼功能。主流的系統架構有如下幾種方式:

1. 一主一從 / 一主多從

一主一從和一主多從是最常見的主從架構方式,一般實現主從配置或者讀寫分離都可以採用這種架構。

如果是一主多從的模式,當 Slave 增加到一定數量時,Slave 對 Master 的負載以及網絡帶寬都會成爲一個嚴重的問題。

2. 多主一從

MySQL 5.7 開始支持多主一從的模式,將多個庫的數據備份到一個庫中存儲。

3. 雙主複製

理論上跟主從一樣,但是兩個MySQL服務器互做對方的從,任何一方有變更,都會複製對方的數據到自己的數據庫。雙主適用於寫壓力比較大的業務場景,或者 DBA 做維護需要主從切換的場景,通過雙主架構避免了重複搭建從庫的麻煩。(主從相互授權連接,讀取對方binlog日誌並更新到本地數據庫的過程;只要對方數據改變,自己就跟着改變)

4. 級聯複製

級聯模式下因爲涉及到的 slave 節點很多,所以如果都連在 master 上對主服務器的壓力肯定是不小的。所以部分 slave 節點連接到它上一級的從節點上。這樣就緩解了主服務器的壓力。

級聯複製解決了一主多從場景下多個從庫複製對主庫的壓力,帶來的弊端就是數據同步延遲比較大。

MySQL 主從複製原理

MySQL 主從複製涉及到三個線程:

一個在主節點的線程:log dump thread

從庫會生成兩個線程:一個 I/O 線程,一個 SQL 線程

如下圖所示:

主庫會生成一個 log dump 線程,用來給從庫 I/O 線程傳 Binlog 數據。

從庫的 I/O 線程會去請求主庫的 Binlog,並將得到的 Binlog 寫到本地的 relay log (中繼日誌)文件中。

SQL 線程,會讀取 relay log 文件中的日誌,並解析成 SQL 語句逐一執行。

主節點 log dump 線程

當從節點連接主節點時,主節點會爲其創建一個 log dump 線程,用於發送和讀取 Binlog 的內容。在讀取 Binlog 中的操作時,log dump 線程會對主節點上的 Binlog 加鎖;當讀取完成發送給從節點之前,鎖會被釋放。主節點會爲自己的每一個從節點創建一個 log dump 線程

從節點I/O線程

當從節點上執行start slave命令之後,從節點會創建一個 I/O 線程用來連接主節點,請求主庫中更新的Binlog。I/O 線程接收到主節點的 log dump 進程發來的更新之後,保存在本地 relay-log(中繼日誌)中。

relay log

這裏又引申出一個新的日誌概念。MySQL 進行主主複製或主從複製的時候會在要複製的服務器下面產生相應的 relay log。

relay log 是怎麼產生的呢?

從服務器 I/O 線程將主服務器的 Binlog 日誌讀取過來,解析到各類 Events 之後記錄到從服務器本地文件,這個文件就被稱爲 relay log。然後 SQL 線程會讀取 relay log 日誌的內容並應用到從服務器,從而使從服務器和主服務器的數據保持一致。中繼日誌充當緩衝區,這樣 master 就不必等待 slave 執行完成才發送下一個事件。

relay log 相關參數查詢:

mysql>  show variables like '%relay%';
+---------------------------+------------------------------------------------------------+
| Variable_name             | Value                                                      |
+---------------------------+------------------------------------------------------------+
| max_relay_log_size        | 0                                                          |
| relay_log                 | yangyuedeMacBook-Pro-relay-bin                             |
| relay_log_basename        | /usr/local/mysql/data/yangyuedeMacBook-Pro-relay-bin       |
| relay_log_index           | /usr/local/mysql/data/yangyuedeMacBook-Pro-relay-bin.index |
| relay_log_info_file       | relay-log.info                                             |
| relay_log_info_repository | TABLE                                                      |
| relay_log_purge           | ON                                                         |
| relay_log_recovery        | OFF                                                        |
| relay_log_space_limit     | 0                                                          |
| sync_relay_log            | 10000                                                      |
| sync_relay_log_info       | 10000                                                      |
+---------------------------+------------------------------------------------------------+
11 rows in set (0.03 sec)

max_relay_log_size

標記 relay log 允許的最大值,如果該值爲 0,則默認值爲 max_binlog_size(1G);如果不爲 0,則max_relay_log_size 則爲最大的 relay_log 文件大小。

relay_log_purge

是否自動清空不再需要中繼日誌時。默認值爲1(啓用)。

relay_log_recovery

當 slave 從庫宕機後,假如 relay log 損壞了,導致一部分中繼日誌沒有處理,則自動放棄所有未執行的 relay log,並且重新從 master 上獲取日誌,這樣就保證了 relay log 的完整性。默認情況下該功能是關閉的,將 relay_log_recovery 的值設置爲 1 時,可在 slave 從庫上開啓該功能,建議開啓。

relay_log_space_limit

防止中繼日誌寫滿磁盤,這裏設置中繼日誌最大限額。但此設置存在主庫崩潰,從庫中繼日誌不全的情況,不到萬不得已,不推薦使用。

sync_relay_log

這個參數和 Binlog 中的 sync_binlog作用相同。當設置爲 1 時,slave 的 I/O 線程每次接收到 master 發送過來的 Binlog 日誌都要寫入系統緩衝區,然後刷入 relay log 中繼日誌裏,這樣是最安全的,因爲在崩潰的時候,你最多會丟失一個事務,但會造成磁盤的大量 I/O。

當設置爲 0 時,並不是馬上就刷入中繼日誌裏,而是由操作系統決定何時來寫入,雖然安全性降低了,但減少了大量的磁盤 I/O 操作。這個值默認是 0,可動態修改,建議採用默認值。

sync_relay_log_info

當設置爲 1 時,slave 的 I/O 線程每次接收到 master 發送過來的 Binlog 日誌都要寫入系統緩衝區,然後刷入 relay-log.info 裏,這樣是最安全的,因爲在崩潰的時候,你最多會丟失一個事務,但會造成磁盤的大量 I/O。當設置爲 0 時,並不是馬上就刷入 relay-log.info 裏,而是由操作系統決定何時來寫入,雖然安全性降低了,但減少了大量的磁盤 I/O 操作。這個值默認是0,可動態修改,建議採用默認值。

從節點 SQL 線程

SQL 線程負責讀取 relay log 中的內容,解析成具體的操作並執行,最終保證主從數據的一致性。

對於每一個主從連接,都需要這三個進程來完成。當主節點有多個從節點時,主節點會爲每一個當前連接的從節點建一個 log dump 進程,而每個從節點都有自己的 I/O 進程,SQL 進程。

從節點用兩個線程將從主庫拉取更新和執行分成獨立的任務,這樣在執行同步數據任務的時候,不會降低讀操作的性能。比如,如果從節點沒有運行,此時 I/O 進程可以很快從主節點獲取更新,儘管 SQL 進程還沒有執行。如果在 SQL 進程執行之前從節點服務停止,至少 I/O 進程已經從主節點拉取到了最新的變更並且保存在本地 relay log 中,當服務再次起來之後就可以完成數據的同步。

要實施複製,首先必須打開 Master 端的 Binlog 功能,否則無法實現。

因爲整個複製過程實際上就是 Slave 從 Master 端獲取該日誌然後再在自己身上完全順序的執行日誌中所記錄的各種操作。如下圖所示:

複製的基本過程
  1. 在從節點上執行 sart slave 命令開啓主從複製開關,開始進行主從複製。從節點上的 I/O 進程連接主節點,並請求從指定日誌文件的指定位置(或者從最開始的日誌)之後的日誌內容。
  2. 主節點接收到來自從節點的 I/O 請求後,通過負責複製的 I/O 進程(log Dump Thread)根據請求信息讀取指定日誌指定位置之後的日誌信息,返回給從節點。返回信息中除了日誌所包含的信息之外,還包括本次返回的信息的 Binlog file 以及 Binlog position(Binlog 下一個數據讀取位置)。
  3. 從節點的 I/O 進程接收到主節點發送過來的日誌內容、日誌文件及位置點後,將接收到的日誌內容更新到本機的 relay log 文件(Mysql-relay-bin.xxx)的最末端,並將讀取到的 Binlog文件名和位置保存到master-info 文件中,以便在下一次讀取的時候能夠清楚的告訴 Master :“ 我需要從哪個 Binlog 的哪個位置開始往後的日誌內容,請發給我”。
  4. Slave 的 SQL 線程檢測到relay log 中新增加了內容後,會將 relay log 的內容解析成在能夠執行 SQL 語句,然後在本數據庫中按照解析出來的順序執行,並在 relay log.info 中記錄當前應用中繼日誌的文件名和位置點。

MySQL 基於 Binlog 主從複製的模式介紹

MySQL 主從複製默認是 異步的模式。MySQL增刪改操作會全部記錄在 Binlog 中,當 slave 節點連接 master 時,會主動從 master 處獲取最新的 Binlog 文件。並把 Binlog 存儲到本地的 relay log 中,然後去執行 relay log 的更新內容。

異步模式 (async-mode)

異步模式如下圖所示:

這種模式下,主節點不會主動推送數據到從節點,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主節點如果崩潰掉了,此時主節點上已經提交的事務可能並沒有傳到從節點上,如果此時,強行將從提升爲主,可能導致新主節點上的數據不完整。

半同步模式(semi-sync)

介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到 relay log 中才返回成功信息給客戶端(只能保證主庫的 Binlog 至少傳輸到了一個從節點上),否則需要等待直到超時時間然後切換成異步模式再提交。

相對於異步複製,半同步複製提高了數據的安全性,一定程度的保證了數據能成功備份到從庫,同時它也造成了一定程度的延遲,但是比全同步模式延遲要低,這個延遲最少是一個 TCP/IP 往返的時間。所以,半同步複製最好在低延時的網絡中使用。

半同步模式不是 MySQL 內置的,從 MySQL 5.5 開始集成,需要 master 和 slave 安裝插件開啓半同步模式。

全同步模式

指當主庫執行完一個事務,然後所有的從庫都複製了該事務併成功執行完才返回成功信息給客戶端。因爲需要等待所有從庫執行完該事務才能返回成功信息,所以全同步複製的性能必然會收到嚴重的影響。

Binlog 複製實戰

配置 my.cnf

[mysqld]
log-bin
server-id
gtid_mode=off #禁掉 gtid

添加主從複製用戶:

grant replication slave on *.* to 'repl'@'%' identified by 'gtidUser';
flush privileges;

然後我們新增一個從庫。

接着我們用命令行的方式來加載主庫的 Binlog 到從庫,這裏可以設置指定的 binlog 文件和位移值。在從庫執行以下命令:

mysql>change master to
master_host='192.168.199.117',
master_user='slave',
master_port=7000,
master_password='slavepass',
master_log_file='mysql-bin.000008',
master_log_pos=0;

mysql>start slave;
mysql>show slave status\G;

複製過程中如果出現代碼性錯誤,個人根據錯誤日誌來決定是否要跳過錯誤繼續執行:

mysql>stop slave;
mysql>set global sql_slave_skip_counter=1;

主從複製可能會出現的問題

Slave 同步延遲

因爲 Slave 端是通過 I/O thread 單線程來實現數據解析入庫;而 Master 端寫 Binlog 由於是順序寫效率很高,當主庫的 TPS 很高的時候,必然 Master 端的寫效率要高過 Slave 端的讀效率,這時候就有同步延遲的問題。

I/O Thread 的同步是基於庫的,即同步幾個庫就會開啓幾個 I/O Thread。

可以通過 show slave status 命令查看 Seconds_Behind_Master 的值來看是否出現同步延遲,這個值代表主從同步延遲的時間,值越大說明延遲越嚴重。值爲 0 爲正常情況,正值表示已經出現延遲,數字越大從庫落後主庫越多。

基於 Binlog 的複製方式肯定有這種問題,MySQL 官方也意識到,單線程不如多線程強,所以在 MySQL 5.7 版本引入了基於組提交的並行複製(官方稱爲Enhanced Multi-threaded Slaves,即MTS),設置參數:

slave_parallel_workers>0 即可,並且 global.slave_parallel_type=‘LOGICAL_CLOCK’

即可支持一個 schema(庫) 下,slave_parallel_workers個 worker 線程併發執行 relay log 中主庫提交的事務。

其核心思想:

一個組提交的事務都是可以並行回放(配合binary log group commit);

slave 機器的 relay log 中 last_committed 相同的事務(sequence_num不同)可以併發執行。其中,變量 slave-parallel-type 可以有兩個值:

  1. DATABASE 默認值,基於庫的並行複製方式
  2. LOGICAL_CLOCK,基於組提交的並行複製方式

MySQL 5.7 開啓 MTS 很簡單,只需要在 Slave 從數據庫的 my.cnf 文件中如下配置即可:

# slave
 slave-parallel-type=LOGICAL_CLOCK
 slave-parallel-workers=8        #一般建議設置4-8,太多的線程會增加線程之間的同步開銷
 master_info_repository=TABLE
 relay_log_info_repository=TABLE
 relay_log_recovery=ON

當然多線程帶來的並行複製方案也有很多實現難點,比如事務都是有序執行的,如果並行回放會不會存在執行數據錯亂的問題。這些問題就不在本節解釋,大家有興趣可以繼續深究。

新一代主從複製模式 - GTID 複製模式

在傳統的複製裏面,當發生故障,需要主從切換,需要找到 Binlog 和 位點信息,恢復完成數據之後將主節點指向新的主節點。在 MySQL 5.6 裏面,提供了新的數據恢復思路,只需要知道主節點的 IP、端口以及賬號密碼就行,因爲複製是自動的,MySQL 會通過內部機制 GTID自動找點同步。

基於 GTID 的複製是 MySQL 5.6.5 後新增的複製方式。

GTID (global transaction identifier) 即全局事務 ID,一個事務對應一個 GTID,保證了在每個在主庫上提交的事務在集羣中有一個唯一的 ID。

GTID複製原理

在原來基於日誌的複製中,從庫需要告知主庫要從哪個偏移量進行增量同步, 如果指定錯誤會造成數據的遺漏,從而造成數據的不一致。

而基於 GTID 的複製中,從庫會告知主庫已經執行的事務的 GTID 的值,然後主庫會將所有未執行的事務的 GTID 的列表返回給從庫,並且可以保證同一個事務只在指定的從庫執行一次,通過全局的事務 ID 確定從庫要執行的事務的方式代替了以前需要用 Binlog 和 位點確定從庫要執行的事務的方式

基於 GTID 的複製過程如下:

  1. master 更新數據時,會在事務前產生 GTID,一同記錄到 Binlog 日誌中。
  2. slave 端的 I/O 線程將變更的 Binlog,寫入到本地的 relay log 中,讀取值是根據gitd_next變量,告訴我們 slave 下一個執行哪個 GTID。
  3. SQL 線程從 relay log 中獲取 GTID,然後對比 slave 端的 Binlog 是否有記錄。如果有記錄,說明該 GTID 的事務已經執行,slave 會忽略。
  4. 如果沒有記錄,slave 就會從 relay log 中執行該 GTID 的事務,並記錄到 Binlog。
  5. 在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果沒有二級索引就用全部掃描。
GTID 組成

​ GTID = source_id:transaction_id

source_id 正常即是 server_uuid,在第一次啓動時生成(函數 generate_server_uuid),並持久化到 DATADIR/auto.cnf 文件裏。

transaction_id順序化的序列號(sequence number),在每臺 MySQL 服務器上都是從 1 開始自增長的序列,是事務的唯一標識。

GTID 生成

GTID 的生成受 gtid_next 控制。

在 Master 上,gtid_next 是默認的 AUTOMATIC,即 GTID 在每次事務提交時自動生成。它從當前已執行的 GTID 集合(即 gtid_executed)中,找一個大於 0 的未使用的最小值作爲下個事務 GTID。在實際的更新事務記錄之前將 GTID 寫入到 Binlog。

在 Slave 上,從 Binlog 先讀取到主庫的 GTID(即 set gtid_next 記錄),而後執行的事務採用該 GTID。

GTID 的好處
  1. GTID 使用 master_auto_position=1 代替了 Binlog 的主從複製方案,相比 Binlog 方式更容易搭建主從複製。
  2. GTID 方便實現主從之間的 failover(主從切換),不用一步一步的去定位 Binlog日誌文件和查找 Binlog 的位點信息。
GTID 模式複製侷限性
  1. 在一個事務裏面混合使用引擎,如 Innodb(支持事務)、MyISAM(不支持事務), 造成多個 GTIDs 和同一個事務相關聯出錯。

  2. CREATE TABLE…..SELECT 不能使用,該語句產生的兩個 Event。 在某一情況會使用同一個 GTID(同一個 GTID 在 slave 只能被使用一次):

    • event one:創建表語句 create table
    • event two :插入數據語句 insert
  3. CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE 不能在事務內使用 (啓用了 –enforce-gtid-consistency 參數)。

  4. 使用 GTID 複製從庫跳過錯誤時,不支持 sql_slave_skip_counter 參數的語法。

GTID 主從複製實戰

1.Master 主數據庫上的操作

在 my.cnf 文件中配置 GTID 主從複製

[root@mysql-master ~]# cp /etc/my.cnf /etc/my.cnf.bak
[root@mysql-master ~]# >/etc/my.cnf
[root@mysql-master ~]# cat /etc/my.cnf
[mysqld]
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
  
symbolic-links = 0
  
log-error = /var/log/mysqld.log
pid-file = /var/run/mysqld/mysqld.pid
  
#GTID:
server_id = 1
gtid_mode = on
enforce_gtid_consistency = on
    
#binlog
log_bin = mysql-bin
log-slave-updates = 1
binlog_format = row
sync-master-info = 1
sync_binlog = 1
   
#relay log
skip_slave_start = 1

配置後,重啓 MySQL 服務:

[root@mysql-master ~]# systemctl restart mysqld

登錄 MySQL,並查看 Master 狀態, 發現多了一項 Executed_Gtid_Set

mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
  
mysql> show global variables like '%uuid%';
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_uuid   | 317e2aad-1565-11e9-9c2e-005056ac6820 |
+---------------+--------------------------------------+
1 row in set (0.00 sec)

查看確認 GTID 功能打開:

mysql> show global variables like '%gtid%';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| binlog_gtid_simple_recovery      | ON    |
| enforce_gtid_consistency         | ON    |
| gtid_executed                    |       |
| gtid_executed_compression_period | 1000  |
| gtid_mode                        | ON    |
| gtid_owned                       |       |
| gtid_purged                      |       |
| session_track_gtids              | OFF   |
+----------------------------------+-------+
8 rows in set (0.00 sec)    

查看確認 Binlog 日誌功能打開:

mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.00 sec)

授權 slave 複製用戶,並刷新權限:

mysql> flush privileges;
Query OK, 0 rows affected (0.04 sec)
  
mysql> show grants for slave@'172.23.3.66';
+-------------------------------------------------------------------------------+
| Grants for [email protected]                                                |
+-------------------------------------------------------------------------------+
| GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'172.23.3.66' |
+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)
 

再次查看 master 狀態:

mysql> show master status;
+-------------------+----------+--------------+------------------+------------------------------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
+-------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000001 |      622 |              |                  | 317e2aad-1565-11e9-9c2e-005056ac6820:1-2 |
+-------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)

這裏需要注意一下:
啓動配置之前,同樣需要對從服務器進行初始化。對從服務器初始化的方法基本和基於日誌點是相同的,只不過在啓動了 GTID 模式後,在備份中所記錄的就不是備份時的二進制日誌文件名和偏移量了,而是記錄的是備份時最後的 GTID 值。
需要先在主數據庫機器上把目標庫備份一下,假設這裏目標庫是 slave_test:

mysql> CREATE DATABASE slave_test CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.02 sec)
  
mysql> use slave_test;
Database changed
mysql> create table user (id int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);
Query OK, 0 rows affected (0.27 sec)
  
mysql> insert into slave_test.user values(1,"xiaoming"),(2,"xiaohong"),(3,"xiaolv");   
Query OK, 3 rows affected (0.06 sec)
Records: 3  Duplicates: 0  Warnings: 0
  
mysql> select * from slave_test.user;
+----+----------+
| id | name     |
+----+----------+
|  1 | xiaoming |
|  2 | xiaohong |
|  3 | xiaolv   |
+----+----------+
3 rows in set (0.00 sec)

把 slave_test 庫備份出來:

[root@mysql-master ~]# mysqldump --single-transaction --master-data=2 --triggers --routines --databases slave_test -uroot -p123456 > /root/user.sql

這裏有個版本上的問題:

MySQL 5.6 使用 mysqldump 備份時,指定備份的具體庫,使用 --database

MySQL 5.7 使用 mysqldump 備份時,指定備份的具體庫,使用--databases。

然後把備份的/root/user.sql 文件拷貝到 slave 從數據庫服務器上。

[root@mysql-master ~]# rsync -e "ssh -p20" -avpgolr /root/user.sql 

到這裏主庫的操作結束,包含 GTID 的備份數據已經 copy 到從庫,下面來進行從庫的操作。

2.從庫操作

在 my.cnf 文件中配置 GTID 主從複製

與主服務器配置大概一致,除了 server_id 不一致外,從服務器還可以在配置文件裏面添加read_only=on ,使從服務器只能進行讀取操作,此參數對超級用戶無效,並且不會影響從服務器的複製。

[root@mysql-slave1 ~]# >/etc/my.cnf
[root@mysql-slave1 ~]# vim /etc/my.cnf
[mysqld]
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
  
symbolic-links = 0
  
log-error = /var/log/mysqld.log
pid-file = /var/run/mysqld/mysqld.pid
  
#GTID:
server_id = 2
gtid_mode = on
enforce_gtid_consistency = on
    
#binlog
log_bin = mysql-bin
log-slave-updates = 1
binlog_format = row
sync-master-info = 1
sync_binlog = 1
   
#relay log
skip_slave_start = 1
read_only = on

配置完成後,重啓mysql服務。

[root@mysql-slave1 ~]# systemctl restart mysql

接着將主數據庫目標庫的備份數據 user.sql導入到從數據庫裏。

[root@mysql-slave1 ~]# ls /root/user.sql
/root/user.sql
[root@mysql-slave1 ~]# mysql -p123456
.........
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)
  
mysql> source /root/user.sql;
  
mysql> select * from slave.test;
+----+----------+
| id | name     |
+----+----------+
|  1 | xiaoming |
|  2 | xiaohong |
|  3 | xiaolv   |
+----+----------+
3 rows in set (0.00 sec)

在從數據庫裏,使用 change master 配置主從複製:

mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
  
mysql> change master to master_host='172.23.3.66',master_user='slave1',master_password='123456',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.26 sec)
  
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
  
mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.23.3.66
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 1357
               Relay_Log_File: mysql-slave1-relay-bin.000002
                Relay_Log_Pos: 417
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
................
................
            Executed_Gtid_Set: 317e2aad-1565-11e9-9c2e-005056ac6820:1-5
                Auto_Position: 1

由此,Master 和 Slave 節點已經配置了主從同步關係。接下來你可以自行在主庫插入一條數據觀察從庫是否同步過來。

使用 GTID 添加從庫有兩種方式

直接同步主庫所有GTID

如果主庫一開始就開啓了 GTID,那麼可以直接獲取主庫的所有GTID來同步至從庫。但是如果主庫 Binlog 日誌太多,那麼相應同步的時間也會變長。這種方式適用於小數據量的同步。

使用這種方式來同步相應的命令爲:

mysql>change master to master_host='xxxxxxx',master_user='xxxxxx',master_password='xxxxx',MASTER_AUTO_POSITION=1;
mysql> start slave;
mysql> stop slave io_thread; #重啓 io 線程,刷新狀態
mysql> start slave io_thread;

當使用 MASTER_AUTO_POSITION 參數的時候,MASTER_LOG_FILEMASTER_LOG_POS 參數不能使用。
如果想要從 GTID 配置回 pos,再次執行這條語句,不過把 MASTER_AUTO_POSITION 置爲 0。

通過設定範圍進行同步

通過指定 GTID 的範圍,然後通過在 slave 設置 @@GLOBAL.GTID_PURGED 從而跳過備份包含的 GTID 。

這種方案適用於數據量比較大一次同步需要耗費巨量時間的數據。但同時也有操作複雜的問題,需要你記住每次同步的範圍。

用這種方式來同步相應的命令爲:

mysql>change master to master_host='xxxxxxx',master_user='xxxxxx',master_password='xxxxx',MASTER_LOG_POS='xxxx';
mysql> start slave;
mysql> stop slave io_thread; #重啓 io 線程,刷新狀態
mysql> start slave io_thread;

這裏注意到我們的參數換了:MASTER_LOG_POS,該參數表示當前需要同步的 GTID 事務的起點值。

總結

本篇介紹主從複製的兩種形式:基於 Binlog 和 位點信息的傳統複製方式;基於 Binlog 和 GTID 的新式複製方式。現在很多公司可能還在使用 MySQL 5.6 的版本,所以 GTID不一定可以使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章