GreatSQL 非同步複製及搭建
一、簡介
複製就是將一個資料庫資料複製到一個或多個資料庫上,複製的過程是非同步的,其工作原理是透過binlog(二進位制日誌)記錄事務變更然後傳送到從庫並重放事務,保持資料一致
二、複製過程
1-1 複製過程圖
2.1 binlog日誌
GreatSQL 複製是基於 binlog 日誌來實現複製的
2.1.1 二進位制日誌輸出格式比較
二進位制日誌格式 | 記錄內容 | 主從同步使用場景 | 大小 | 效能 |
---|---|---|---|---|
statement | 基於SQL | 如果使用了一些不確定性的函式和自定義函式,函式返回的資料在主從庫上不一致。 比如 now(),last_insert_id()等。 | 較小 | 最好 |
row | 基於資料行 | 預設使用基於row | 較大 | 最差 |
mixed | 混合格式 | 預設使用statement。 當statement無法正確複製時,採用rows | 居中 |
2.2 複製過程
-
主庫把資料更新事件寫入二進位制日誌。
-
從庫的IO執行緒向主庫請求二進位制日誌事件。
-
主庫的binlog dump執行緒向從庫IO執行緒傳送二進位制日誌事件。
-
從庫的IO執行緒將二進位制日誌事件寫入中繼日誌。
-
從庫的SQL執行緒應用中繼日誌中的事件。
2.3 二階段提交
GreatSQL 包含兩種記錄資料變更的日誌,redolog、binlog為了保證兩個日誌的對資料變更事件達到一致性,GreatSQL 內部使用XA來實現,其核心是兩階段提交。
2.3.1 事務提交流程
主從複製中,從庫是透過binlog日誌重放來實現複製。如何保證主從的資料一致性,就需要考慮如下兩方面
-
binlog記錄的事務一定不比redolog少。
-
binlog與redolog記錄的事務的順序性是一致的。
在兩階段協議中一般分為事務管理器(協調者)和若干事務執行器(參與者)兩種角色。GreatSQL 內部實現的兩階段提交中,二進位制日誌充當了協調組角色,由它來通知InnoDB執行準備、提交和回滾。從實現角度分析,事務提交有準備階段和提交階段組成。兩階段提交流程如下圖:
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引數控制。
-
重做日誌刷盤方式
-
innodb_flush_log_at_trx_commit引數為1時,表示只要事務提交,立即將重做日誌刷盤。
-
innodb_flush_log_at_trx_commit引數為2時,表示每秒將重做日誌緩衝區的內容寫入到作業系統頁面緩衝,至於什麼時候刷盤,由作業系統控制。
-
innodb_flush_log_at_trx_commit引數為0時,表示每秒將重做日誌刷盤。
-
-
二進位制日誌刷盤方式
- sync_binlog引數為1時,表示只要事務提交,立即將二進位制日誌刷盤。
- sync_binlog引數為N(N>1)時,表示N個二進位制日誌組提交後,將二進位制日誌刷盤。
- 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上的操作
-
建立用於複製的賬戶,並授予相應的許可權。
-
停止源資料庫服務。
-
複製源資料庫上的資料檔案到從庫。
-
啟動源資料庫服務。
-
-
Slave上的操作
-
刪除從庫資料目錄中的auto.cnf,從庫在啟動時會自動生成唯一的server_uuid。檢查資料庫配置檔案確保server_id是唯一的。
-
啟動從資料庫服務。
-
配置主從同步關係,並啟動主從同步執行緒。
-
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上的操作
- 建立源庫資訊
greatsql> change master to master_host='192.168.135.183',master_port=3305,master_user='repl',master_password='!QAZ2wsx';
- 使用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上的操作
- 在源庫上建立全量備份
$ 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
- 準備資料資訊備份
$ xtrabackup --prepare --target-dir=/mysql/backup 2>restore.log
--prepare
引數準備備份資料進行恢復。資料檔案在準備之前是不一致的,因為它們是在備份程式執行的不同時間複製的,並且在這個時間段,有些資料已經發生變更。其原理是使用redolog進行後滾,使用undolog進行前滾。
-
Slave上的操作
- 關閉從庫,在從庫上刪除資料庫初始化生成的資料庫檔案。
$ rm -rf /mysql/dbdata/data/*;rm -rf /mysql/dbdata/log/*
- 從源庫上拉取備份恢復後的資料檔案。
$ 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
- 啟動從資料庫服務,並配置主從同步。
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
技術交流群:
微信:掃碼新增
GreatSQL社群助手
微信好友,傳送驗證資訊加群
。