摘要
定期備份的重要性在資料庫生命周期中已得到展現。有不同的風格:二進制的(Percona XtraBackup),二進制日志備份,磁盤快照(lvm,ebs等)和經典的:邏輯備份,可以使用mysqldump,mydumper或mysqlpump等工具進行的備份。它們每個都有特定的用途,MTTR,保留政策等。
另一個事實是,一旦datadir增長,進行備份可能是一項非常緩慢的任務:存儲更多資料,讀取和備份更多資料。而且,另一個事實是,不僅資料會增長,而且環境中可用的MySQL執行個體的數量也會增加(通常)。那麼,為什麼不利用更多的MySQL執行個體來進行邏輯備份以使此操作更快呢?
分布式備份(或使用所有可用的從站)
這個想法很簡單:不要從單個伺服器上擷取整個備份,而要使用所有可用的伺服器。本概念證明僅專注于在主/從拓撲上使用副本。也可以使用Master,但是在這種情況下,我決定不使用它,以免增加備份開銷。
測試
在主/從屬拓撲中:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2PnVGcq5ycqJjNqNDd3hXOvwVO0QDO2ITMtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpeg)
來自Orchestrator GUI的圖形
使用約64GB資料(不包括索引大小)和300個表(模式“ sb”)的小datadir:
+--------------+--------+--------+-----------+----------+-----------+----------+
| TABLE_SCHEMA | ENGINE | TABLES | ROWS | DATA (M) | INDEX (M) | TOTAL(M) |
+--------------+--------+--------+-----------+----------+-----------+----------+
| meta | InnoDB | 1 | 0 | 0.01 | 0.00 | 0.01 |
| percona | InnoDB | 1 | 2 | 0.01 | 0.01 | 0.03 |
| sb | InnoDB | 300 | 295924962 | 63906.82 | 4654.68 | 68561.51 |
| sys | InnoDB | 1 | 6 | 0.01 | 0.00 | 0.01 |
+--------------+--------+--------+-----------+----------+-----------+----------+
複制
使用3個副本,使用mysqldump進行的分布式邏輯備份花費了6分13秒:
[root@mysql1 ~]# ls -lh /data/backups/20200101/
total 56G
-rw-r--r--. 1 root root 19G Jan 1 14:37 mysql2.sql
-rw-r--r--. 1 root root 19G Jan 1 14:37 mysql3.sql
-rw-r--r--. 1 root root 19G Jan 1 14:37 mysql4.sql
[root@mysql1 ~]# stat /data/backups/20200101/mysql2.sql
File: '/data/backups/20200101/mysql2.sql'
Size: 19989576285 Blocks: 39042144 IO Block: 4096 regular file
Device: 10300h/66304d Inode: 54096034 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:unlabeled_t:s0
Access: 2020-01-01 14:31:34.948124516 +0000
Modify: 2020-01-01 14:37:41.297640837 +0000
Change: 2020-01-01 14:37:41.297640837 +0000
Birth: -
複制
單個副本上的相同備份類型花費了11分59秒:
[root@mysql1 ~]# time mysqldump -hmysql2 --single-transaction --lock-for-backup sb > /data/backup.sql
real 11m58.816s
user 9m48.871s
sys 2m6.492s
[root@mysql1 ~]# ls -lh /data/backup.sql
-rw-r--r--. 1 root root 56G Jan 1 14:52 /data/backup.sql
複制
換一種說法:
分布式伺服器快48%!
這是一個相當小的資料集。值得一試。那麼它是怎樣工作的?
概念
邏輯很簡單,可以分為多個階段。
階段1:準備
- 找出可用的副本數
- 找出要備份的架構中的表數
- 在所有可用副本之間劃分表的數量。結果塊将是每個副本将備份的表。
階段2:保證一緻性
- 阻止主伺服器執行更改二進制日志位置的操作。通常,這是通過帶有讀取鎖的FLUSH TABLES完成的,但是此PoC使用的是Percona Server for MySQL上的LOCK BINLOG FOR BACKUP的很酷的功能, 并且破壞性較小。
- 查找最新副本
- 使用START SLAVE UNTIL使所有其他副本與最新副本比對
- 使用相應的表塊為每個副本啟動一個mysqldump,并使用–lock-for-backup(Percona Server的另一個功能)
完整的腳本可以在這裡找到:
https://github.com/nethalo/parallel-mysql-backup/blob/master/dist_backup.sh
值得一提的是,腳本具有自己的日志,該日志将描述每個步驟,它看起來像這樣:
[200101-16:01:19] [OK] Found 'mysql' bin
[200101-16:01:19] [Info] SHOW SLAVE HOSTS executed
[200101-16:01:19] [Info] Count tables OK
[200101-16:01:19] [Info] table list gathered
[200101-16:01:19] [Info] CREATE DATABASE IF NOT EXISTS percona
[200101-16:01:19] [Info] CREATE TABLE IF NOT EXISTS percona.metabackups
[200101-16:01:19] [Info] TRUNCATE TABLE percona.metabackups
[200101-16:01:19] [Info] Executed INSERT INTO percona.metabackups (host,chunkstart) VALUES('mysql3',0)
[200101-16:01:19] [Info] Executed INSERT INTO percona.metabackups (host,chunkstart) VALUES('mysql4',100)
[200101-16:01:19] [Info] Executed INSERT INTO percona.metabackups (host,chunkstart) VALUES('mysql2',200)
[200101-16:01:19] [Info] lock binlog for backup set
[200101-16:01:19] [Info] slave status position on mysql3
[200101-16:01:19] [Info] slave status file on mysql3
[200101-16:01:19] [Info] slave status position on mysql4
[200101-16:01:19] [Info] slave status file on mysql4
[200101-16:01:19] [Info] slave status position on mysql2
[200101-16:01:19] [Info] slave status file on mysql2
[200101-16:01:19] [Info] set STOP SLAVE; START SLAVE UNTIL MASTER_LOG_FILE = 'mysql-bin.000358', MASTER_LOG_POS = 895419795 on mysql3
[200101-16:01:20] [Info] set STOP SLAVE; START SLAVE UNTIL MASTER_LOG_FILE = 'mysql-bin.000358', MASTER_LOG_POS = 895419795 on mysql4
[200101-16:01:20] [Info] set STOP SLAVE; START SLAVE UNTIL MASTER_LOG_FILE = 'mysql-bin.000358', MASTER_LOG_POS = 895419795 on mysql2
[200101-16:01:20] [Info] Created /data/backups/20200101/ directory
[200101-16:01:20] [Info] Limit chunk OK
[200101-16:01:20] [Info] Tables list for mysql3 OK
[200101-16:01:20] [OK] Dumping mysql3
[200101-16:01:20] [Info] Limit chunk OK
[200101-16:01:20] [Info] Tables list for mysql4 OK
[200101-16:01:20] [OK] Dumping mysql4
[200101-16:01:20] [Info] Limit chunk OK
[200101-16:01:20] [Info] Tables list for mysql2 OK
[200101-16:01:20] [OK] Dumping mysql2
[200101-16:01:20] [Info] UNLOCK BINLOG executed
[200101-16:01:20] [Info] set start slave on mysql3
[200101-16:01:20] [Info] set start slave on mysql4
[200101-16:01:20] [Info] set start slave on mysql2
複制
一些基本要求
由于該工具使用指令SHOW SLAVE HOSTS ,是以必須設定變量report_host,如果使用的是Orchestrator,則很可能已經設定了該變量。
在“ report_host”變量中設定的主機應該是可通路的主機。例如,可以實際解析的IP或主機(DNS,編輯/ etc / hosts檔案)。
任何涉及的副本上都沒有複制過濾器。這樣可以保證資料的一緻性。
該腳本目前應在主伺服器中本地運作。
由于使用了備份鎖,是以隻能在Percona Server上使用。
預計MySQL使用者憑據将在.my.cnf檔案内的主目錄中可用