GreatSQL 非同步複製及搭建

GreatSQL發表於2024-09-11

GreatSQL 非同步複製及搭建

一、簡介

複製就是將一個資料庫資料複製到一個或多個資料庫上,複製的過程是非同步的,其工作原理是透過binlog(二進位制日誌)記錄事務變更然後傳送到從庫並重放事務,保持資料一致

二、複製過程

file

1-1 複製過程圖

2.1 binlog日誌

GreatSQL 複製是基於 binlog 日誌來實現複製的

2.1.1 二進位制日誌輸出格式比較

二進位制日誌格式 記錄內容 主從同步使用場景 大小 效能
statement 基於SQL 如果使用了一些不確定性的函式和自定義函式,函式返回的資料在主從庫上不一致。 比如 now(),last_insert_id()等。 較小 最好
row 基於資料行 預設使用基於row 較大 最差
mixed 混合格式 預設使用statement。 當statement無法正確複製時,採用rows 居中

2.2 複製過程

  1. 主庫把資料更新事件寫入二進位制日誌。

  2. 從庫的IO執行緒向主庫請求二進位制日誌事件。

  3. 主庫的binlog dump執行緒向從庫IO執行緒傳送二進位制日誌事件。

  4. 從庫的IO執行緒將二進位制日誌事件寫入中繼日誌。

  5. 從庫的SQL執行緒應用中繼日誌中的事件。

2.3 二階段提交

GreatSQL 包含兩種記錄資料變更的日誌,redolog、binlog為了保證兩個日誌的對資料變更事件達到一致性,GreatSQL 內部使用XA來實現,其核心是兩階段提交。

2.3.1 事務提交流程

主從複製中,從庫是透過binlog日誌重放來實現複製。如何保證主從的資料一致性,就需要考慮如下兩方面

  1. binlog記錄的事務一定不比redolog少。

  2. binlog與redolog記錄的事務的順序性是一致的。

在兩階段協議中一般分為事務管理器(協調者)和若干事務執行器(參與者)兩種角色。GreatSQL 內部實現的兩階段提交中,二進位制日誌充當了協調組角色,由它來通知InnoDB執行準備、提交和回滾。從實現角度分析,事務提交有準備階段和提交階段組成。兩階段提交流程如下圖:

file

1-2事務提交流程

1、事務發起commit請求。

2、呼叫binlog-hton和innobase-hton的prepare方法完成第一階段。binlog-hton的方法什麼也沒有做,innodb的prepare持有prepare_commit_mutex鎖,將重做日誌刷盤,並將事務狀態設定為prepared。

3、如果事務涉及的所有儲存引擎的prepare都執行成功,則呼叫TC_LOG_BIN:log_xid將事務寫入到二進位制日誌。

4、最後,呼叫儲存引擎的commit完成事務的提交,向重做日誌寫入commit標記,釋放prepare_commit_mutex,並將事務設定為trx_not_started狀態。

2.3.2 InnoDB恢復

資料庫在奔潰恢復時,不同狀態的事務,會進行不同的處理。

  • trx_commit_in_memory的事務,清除回滾段後,將事務設定為trx_commit_not_started。

  • trx_commit_active的事務,直接回滾。

  • trx_not_started的事務,表示事務已提交過,跳過。

  • trx_commit_prepared的事務,要根據二進位制日誌來決定事務是否提交,暫時跳過。

在資料庫發生奔潰時,資料庫根據重做日誌進行資料恢復,逐個檢查重做日誌的每個事務狀態。根據1-2的流程,如果已經進行到trx_not_started階段,也就是儲存引擎commit階段,那麼說明重做日誌和二進位制日誌是一致的,正常根據重做日誌的內容進行恢復即可。如果事務狀態為trx_active,沒有寫入到二進位制日誌,就直接回滾。如果事務狀態為trx_commit_prepared,要分兩種情況:先檢查二進位制日誌是否寫入成功,如果沒有寫入成功,直接回滾,如果寫入成功了,那就進行最後一步,呼叫儲存引擎commit,更改事務狀態為trx_not_started,也就是真正提交的狀態,可以用作資料恢復。

由此可以,GreatSQL是以二進位制日誌的寫入與否作為事務提交成功與否的標誌。透過這種方式讓InnoDB重做日誌和GreatSQL伺服器的二進位制日誌中的事務狀態保持一致。兩階段提交很好的保持了資料的一致性和順序性。

GreatSQL透過innodb_support_xa系統變數來控制innodb是否支援XA事務的兩階段提交,預設是支援。在GreatSQL8中已移除該變數,表示資料庫內部一直啟用innodb對XA事務兩階段提交的支援。

2.3.3 日誌刷盤頻率

兩階段提交只是從流程上保證了日誌的一致性,如果日誌在寫盤期間,資料庫發生了崩潰或者伺服器當機,存在日誌資料丟失的風險。為了規避此類風險,我們需要配置正確的日誌刷盤頻率。

重做日誌的刷盤頻率由innodb_flush_log_at_commit_trx引數控制。二進位制日誌的刷盤頻率由sync_binlog引數控制。

  • 重做日誌刷盤方式

    1. innodb_flush_log_at_trx_commit引數為1時,表示只要事務提交,立即將重做日誌刷盤。

    2. innodb_flush_log_at_trx_commit引數為2時,表示每秒將重做日誌緩衝區的內容寫入到作業系統頁面緩衝,至於什麼時候刷盤,由作業系統控制。

    3. innodb_flush_log_at_trx_commit引數為0時,表示每秒將重做日誌刷盤。

  • 二進位制日誌刷盤方式

    1. sync_binlog引數為1時,表示只要事務提交,立即將二進位制日誌刷盤。
    2. sync_binlog引數為N(N>1)時,表示N個二進位制日誌組提交後,將二進位制日誌刷盤。
    3. sync_binlog引數為0時,表示二進位制日誌的刷盤由作業系統控制。

三、非同步複製引數

3.1 源庫和複製庫常用引數說明

引數名 引數值 引數級別 作用
binlog_do_db schema 配置檔案修改 二進位制日誌只記錄該引數指定的庫名產生的更新事件
binlog_ignore_db schema 配置檔案修改 二進位制日誌不記錄該引數指定的庫名產出的更新事件。
log_slave_update ON/OFF 系統級別 複製庫應用中繼日誌中的事件是否寫入二進位制日誌。用於複製級聯,建議主庫和從庫都開啟該引數。
replicate_do_db schema 配置檔案修改 只重放中繼日誌中該引數指定的庫名的事件。
replicate_ignore_db schema 配置檔案修改 不重放中繼日誌中該引數指定的庫名的事件。
replicate_wild_do_table schema.% 配置檔案修改 只重放中繼日誌中該引數指定的庫名的事件。 建議使用這種方式進行復制過濾。
replicate_wild_ignore_table schema.% 配置檔案修改 不重放中繼日誌中該引數指定的庫名的事件。 建議使用這種方式進行復制過濾。
skip_slave_start ON/OFF 只讀引數 複製庫啟動時,是否啟動複製執行緒。 建議不開啟該引數。
sql_log_bin ON/OFF 會話級別 會話端執行的更新事件是否寫入二進位制日誌。
slave_parallel_workers 0-N 全域性級別 是否開啟多執行緒複製, 並指定對少個執行緒併發應用複製事務。 引數值為0時,表示不開啟。
slave_parallel_type logical_lock database 全域性級別 在源庫二進位制日誌事件是以組的方式進行提交。 為了保證在從庫併發的執行事務,有兩種方式進行控制。 基於logical_lock的方式: 透過跟蹤某一個時間點內的事務與事務之間的關係, 來決定儘可能的併發執行事務。 基於database的方式: 在不同資料庫之間值的事務可以併發執行。
slave_preserve_commit_order ON/OFF 全域性級別 在多執行緒複製庫上, 事務的執行和提交順序與中繼日誌中記錄的順序一致。
slave_pending_job_size_max integer 全域性級別 在多執行緒複製庫上, 應用佇列用於保留暫未應用的事務的最大可用記憶體。 該引數的值不能小於源庫上max_allowed_packet引數指定的值, 不然在執行大事務事會報錯。
slave_max_allowed_packet integer 全域性級別 指定複製庫上的sql執行緒和io執行緒能夠處理的最大資料包, 該引數不能小於源庫上max_allowed_packet指定的引數值。

四、非同步複製部署

4.1 環境準備

使用兩臺伺服器來部署一主一從的非同步複製。

Master:192.168.135.183

Slave:192.168.135.142

4.2 部署資料庫

安裝GreatSQL資料庫,見GreatSQL官方文件 https://greatsql.cn/docs/8.0.32-25/4-install-guide/3-install-with-tarball.html

4.3 配置複製

4.3.1 空庫

初始安裝的資料庫沒有任何應用資料。可以直接配置就能使用。

  • Master上的操作:

    greatsql> reset master;
    
  • Slave上的操作:

    greatsql> reset master;
    greatsql> reset slave all;
    
    greatsql> change master to master_host="192.168.135.183",master_port=3305,master_user='repl',ma	ster_password='!QAZ2wsx',master_auto_position=1;
    
    greatsql> start slave;
    greatsql> show slave status\G
    

4.3.2 離線

如果源資料庫上存在應用資料,允許在一個接收的離線時間視窗進行復制,那麼我們可以直接把源庫的資料檔案複製到從庫,再啟動從庫進行主從配置。

  • Master上的操作

    1. 建立用於複製的賬戶,並授予相應的許可權。

    2. 停止源資料庫服務。

    3. 複製源資料庫上的資料檔案到從庫。

    4. 啟動源資料庫服務。

  • Slave上的操作

    1. 刪除從庫資料目錄中的auto.cnf,從庫在啟動時會自動生成唯一的server_uuid。檢查資料庫配置檔案確保server_id是唯一的。

    2. 啟動從資料庫服務。

    3. 配置主從同步關係,並啟動主從同步執行緒。

4.3.3 聯機

大多數情況下,複製被要求在不影響線上業務的情況下聯機建立,而且還要求對線上源庫影響越小越好。在聯機情況下,我們通常採用mysqldump和xtrabackup工具複製源庫到從庫,配置主從同步。

mysqldump聯機複製過程

  • Master上的操作

    1.建立用於複製的賬戶

greatsql> create user repl@'%' identified with mysql_native_password by '!QAZ2wsx';
greatsql> grant replication client,replication slave on *.* to repl@'%';
greatsql> flush privileges;
  • Slave上的操作
  1. 建立源庫資訊
greatsql> change master to master_host='192.168.135.183',master_port=3305,master_user='repl',master_password='!QAZ2wsx';
  1. 使用mysqldump匯入資料到從庫,建立複製
greatsql> mysqldump --single-transaction --all-databases --master-data=1 --host=192.168.135.183 --port=3306 --user=root --password=!QAZ2wsx --default-character-set=utf8mb4 --apply-slave-statements|mysql -uroot -p!QAZ2wsx -h192.168.135.142 -P3305

重要引數說明:

  • --single-transaction引數對innodb表執行非鎖定匯出。此選項將事務隔離模式設定為repeatable read,並在轉儲資料之前向伺服器傳送start transaction sql語句。它僅適用於innodb等事務表,因為它會在發出start transaction時轉儲資料庫一致狀態,而不會阻塞任何應用程式。

  • --master-data引數為1時會導致轉儲輸出包含型別change master to master_log_file='binlog.000004',master_log_pos=1230;的sql語句,該語句指示主庫的二進位制日誌座標(檔案和偏移量)。如果選項值為2,則chang master to語句將被註釋,僅提供資訊,不會執行。如果未指定選項值,則預設值為1。

  • --apply-slave-statements引數會在change master to之前新增stop slave語句,被宰輸出的結尾處新增start slave語句,用於開啟複製。

  • --deafult-character-set引數指定預設字符集,GreatSQL的預設字符集為utf8mb4。

xtrabackup聯機複製過程

  • Master上的操作

    1. 在源庫上建立全量備份
    $ xtrabackup --defaults-file=/mysql/conf/node13306.cnf --host='192.168.135.183' --port=3306 --user='root' --password='!QAZ2wsx' --backup --target-dir=/mysql/backup 2>backup.log
    
    1. 準備資料資訊備份
    $ xtrabackup --prepare --target-dir=/mysql/backup 2>restore.log
    

--prepare引數準備備份資料進行恢復。資料檔案在準備之前是不一致的,因為它們是在備份程式執行的不同時間複製的,並且在這個時間段,有些資料已經發生變更。其原理是使用redolog進行後滾,使用undolog進行前滾。

  • Slave上的操作

    1. 關閉從庫,在從庫上刪除資料庫初始化生成的資料庫檔案。
    $ rm -rf /mysql/dbdata/data/*;rm -rf /mysql/dbdata/log/*
    
    1. 從源庫上拉取備份恢復後的資料檔案。
    $ scp  -r [root@192.168.135.183:/mysql/backup/*](mailto:root@192.168.1.111:/mysql/backup/*) /mysql/dbdata/data
    
    $ mv binlog.* ib_logfile* undo_00* ../log/
    
    $ chown -R mysql:mysql /mysql/dbdata
    
    1. 啟動從資料庫服務,並配置主從同步。
    greatsql> service mysql start
    
    greatsql> change master to master_host="192.168.135.183",master_port=3305,master_user='repl',ma	ster_password='!QAZ2wsx',master_auto_position=1;
    

五、非同步複製常見問題說明

5.1 show slave 重點指標說明

我們在從庫執行show slave status來觀察主從同步的狀態。

  • master_log_file:I/O執行緒正在讀取的master binlog。

  • read_master_log_pos:I/O執行緒已經讀取到master binlog的位置。

  • relay_log_file:SQL執行緒正在讀取和執行的relay log。

  • relay_log_pos:SQL執行緒已經讀取和執行relay log的位置。

  • relay_master_log_file:SQL執行緒最近執行的操作對應的是哪個master binlog。

  • relay_master_log_pos:SQL執行緒最新執行的操作對應的是master binlog的位置。

  • retrieved_gtid_set:接收到的gtid集合。

  • executed_gtid_set:已執行的gtid集合。

  • seconds_behind_master:SQL執行緒比IO執行緒慢多少。在網路正常的情況下,可以表示從庫比源庫慢多少。

5.2 常見錯誤

主從非同步複製中,存在資料庫丟失的可能性,導致主從資料不一致。如果資料量比較少的情況下,我們在從庫執行相關的操作補齊資料後,對改事務進行跳過。

  • 源庫刪除一行記錄,而slave上找不到改行資料進行刪除操作。錯誤程式碼為1032。

  • 源庫插入一行資料,而slave上表示改行資料早已存在,導致重複衝突。錯誤程式碼為1062。

  • 源庫上更新一行資料,而slave上表示找不到改行資料執行更新操作,錯誤程式碼為1032。

5.3 主從資料校驗

可以使用GreatSQL社群的gt-checksum工具對主從資料進行一致性校驗,或者使用官方工具checksum進行資料校驗。checksum工具對資料庫校驗時,會給表上讀鎖,這一點在使用時需要注意。

gt-checksum工具詳見:https://gitee.com/GreatSQL/gt-checksum


Enjoy GreatSQL 😃

關於 GreatSQL

GreatSQL是適用於金融級應用的國內自主開源資料庫,具備高效能、高可靠、高易用性、高安全等多個核心特性,可以作為MySQL或Percona Server的可選替換,用於線上生產環境,且完全免費併相容MySQL或Percona Server。

相關連結: GreatSQL社群 Gitee GitHub Bilibili

GreatSQL社群:

社群部落格有獎徵稿詳情:https://greatsql.cn/thread-100-1-1.html

image-20230105161905827

技術交流群:

微信:掃碼新增GreatSQL社群助手微信好友,傳送驗證資訊加群

image-20221030163217640

相關文章