使用MySQL SQL線程回放Binlog實現恢復


1. 需求部分

1.1 基於MySQL復制同步特性,嘗試使用Replication的SQL線程來回放binlog,可基於以下邏輯模擬場景

  1. 做全量xtrabackup備份模擬日常備份
  2. 執行sysbench壓測4張表,20個線程,壓測10分鍾,模擬大量binlog
  3. 刪除實例模擬數據庫被誤刪除或硬件故障(binlog需要保留)
  4. 使用xtrabackup恢復全量備份
  5. 使用MySQL Replication SQL線程回放binlog(提示:恢復前需要將relay_log_recocery參數設置為0)

1.2 基於題目1.1,考慮是否可以做到以下場景的恢復

  1. 只恢復單個庫的數據
  2. 只恢復單個表的數據
  3. 將數據恢復到指定的GTID或者position點(如恢復到誤操作drop之前的GTID)
  4. 是否可以通過參數調整提升回放效率,列出提升效率的參數並實際測試用SQL線程回放binlog和直接使用mysqlbinlog回放binlog的性能對比

2.操作部分

2.1 環境准備及故障模擬

  1. 使用mysqlbinlog將binlog文件實時轉儲到備份目錄(當前環境備份目錄配置在/data/mysql/backup)
[root@10-186-61-162 ~]# mkdir -p /data/mysql/backup/binlog
[root@10-186-61-162 ~]# mysqlbinlog --raw --read-from-remote-server -h10.186.61.162 -urepl -pxxx -P3306 --result-file=/data/mysql/backup/binlog/ mysql-bin.000001 --stop-never --stop-never-slave-server-id=100 &

生成sysbench測試數據,創建4張表,每張各100W數據庫並壓測一分鍾模擬數據變化

## 插入基礎數據
[root@10-186-61-162 ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua --db-ps-mode=disable --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sysbench --mysql-password=xxx --mysql-db=sbtest --tables=4 --table-size=1000000 --report-interval=1 --time=600 --threads=20  prepare
 
## 執行sysbench壓測模擬數據變化,壓測1分鍾
[root@10-186-61-162 ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua --db-ps-mode=disable --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sysbench --mysql-password=xxx --mysql-db=sbtest --tables=4 --table-size=1000000 --report-interval=1 --time=60 --threads=20  run

執行物理備份模擬每天的全量備份

[root@10-186-61-162 ~]# innobackupex --host=10.186.61.162 --port=3306 --user=backup --password=xxx  /data/mysql/backup/

繼續執行壓測,模擬備份后的數據變化,壓測10分鍾,模擬大量binlog

[root@10-186-61-162 ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua --db-ps-mode=disable --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sysbench --mysql-password=xxx --mysql-db=sbtest --tables=4 --table-size=1000000 --report-interval=1 --time=600 --threads=20  run

停止並刪除數據庫數據庫模擬誤操作或硬件故障

[root@10-186-61-162 ~]# systemctl stop mysql_3306
[root@10-186-61-162 ~]# rm -rf /data/mysql/data/*

2.2 數據恢復

還原xtrabackup全量備份

[root@10-186-61-162 ~]# cd /data/mysql/backup
[root@10-186-61-162 backup]# innobackupex --apply-log 2020-03-02_17-39-07/
[root@10-186-61-162 backup]# innobackupex --defaults-file=/etc/my.cnf --copy-back 2020-03-02_17-39-07/

將binlog轉換為relay log並拷貝到數據目錄以便SQL線程回放數據

[root@10-186-61-162 backup]# cd /data/mysql/backup/binlog/
 
## 將binlog重命名為relay log
[root@10-186-61-162 binlog]# rename mysql-bin mysql-relay mysql-bin*
 
## 創建relay log index文件
[root@10-186-61-162 binlog]# ls ./mysql-relay.0000* >mysql-relay.index
 
## 拷貝relay log到數據目錄
[root@10-186-61-162 binlog]# cp mysql-relay.* /data/mysql/data/
 
## 修改數據目錄權限
[root@10-186-61-162 binlog]# chown -R mysql:mysql /data/mysql/data/

修改relay_log_recovery參數,設置為0並啟動數據庫,relay_log_recovery為1時,relay log會在復制線程啟動時被清除重新拉

## 獲取備份文件中的binlog位點信息及GTID點對應的relay log文件
[root@10-186-61-162 ~]# cd /data/mysql/backup/2020-03-02_17-39-07/
[root@10-186-61-162 2020-03-02_17-39-07]# cat xtrabackup_binlog_info
mysql-bin.000007	80456866	f41abe78-5c62-11ea-abf1-02000aba3da2:1-52013
 
## 啟動數據庫
[root@10-186-61-162 2020-03-02_17-39-07]# systemctl start mysql_3306
 
## change master指定一個空的主庫,創建SQL線程
root@localhost[(none)]> reset master;
 
## 指定備份文件中對應的binlog位點
root@localhost[(none)]> CHANGE MASTER TO MASTER_HOST='1.1.1.1',RELAY_LOG_FILE='mysql-relay.000007',RELAY_LOG_POS=80456866;
 
## 查看指定的位點是否生效
root@localhost[(none)]> select * from mysql.slave_relay_log_info;
+-----------------+----------------------+---------------+-----------------+----------------+-----------+-------------------+----+--------------+
| Number_of_lines | Relay_log_name       | Relay_log_pos | Master_log_name | Master_log_pos | Sql_delay | Number_of_workers | Id | Channel_name |
+-----------------+----------------------+---------------+-----------------+----------------+-----------+-------------------+----+--------------+
|               7 | ./mysql-relay.000007 |      80456866 |                 |              0 |         0 |                 0 |  1 |              |
+-----------------+----------------------+---------------+-----------------+----------------+-----------+-------------------+----+--------------+
 
## 只需要開啟SQL線程對指定的relay log開始回放即可
root@localhost[(none)]> START SLAVE SQL_THREAD;
 
## 持續執行可看到binlog數據開始回放
root@localhost[(none)]> show slave status\G
 
## 待binlog恢復完成且數據校驗無問題后后可將復制關系重置
root@localhost[(none)]> stop slave;
root@localhost[(none)]> reset slave;
root@localhost[(none)]> reset slave all;

2.3 只恢復單個庫的數據

  • 由於備份是全量備份,無法單庫還原(如果已知表結構可使用可傳輸表空間方式單庫還原),可先將全量恢復后對只對單庫做binlog還原
    • 只需在2.2數據恢復的基礎上增加一條以下命令即可實現對sbtest單庫的binlog還原
    • CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('sbtest.%');

2.4 只恢復單個表的數據

  • 該步驟與單庫還原類似,只需將復制過濾屬性指定為具體的表,如
    • CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('sbtest.sbtest1','sbtest.sbtest2');
    • 可在開啟binlog還原前后對sbtest1-4表做checksum,驗證是否只有sbtest1和sbtest2做了binlog還原
    • checksum table sbtest1,sbtest2,sbtest3,sbtest4;

2.5 恢復到指定的GTID或position點

  • 該步驟只需在2.2數據恢復的基礎上,將START SLAVE SQL_THREAD改為START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS,如只恢復到GTID=499999
    • START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS = 'f41abe78-5c62-11ea-abf1-02000aba3da2:500000;

2.6 提升恢復效率的參數優化

  • set global sync_binlog=0;
  • set global innodb_flush_log_at_trx_commit=0;
  • set global slave_parallel_type=LOGICAL_CLOCK;
  • set global slave_parallel_workers=8;
  • 關閉binlog

2.7 使用復制線程與使用mysqlbinlog恢復的效率對比

  • mysqlbinlog
    • 恢復耗時 722s
  • SQL線程
    • 恢復耗時 151s

2.8 總結

  • 使用SQL線程恢復binlog數據相對比mysqlbinlog有以下優勢
  • 只需配置好復制讓數據庫自動恢復數據即可
  • 可以使用MySQL並行復制特性,提升恢復效率
  • 可以精細化的控制恢復的庫表
  • 可以指定恢復到具體的GTID點以及跳過誤操作的GTID

2.9 恢復優化

  • 假設一個每天凌晨備份,某天早上8點數據庫被誤操作drop了業務庫,請說明恢復的流程
    • 保持主庫當前狀態
    • 使用主庫的備份恢復一個實例
    • 使用change master to后在啟動開啟START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS方式讓復制同步數據到drop操作之前
    • 跳過drop操作的gtid
    • 繼續同步復制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM