vlambda博客
学习文章列表

MySQL物理备份-PXB原理及用法

关于PXB

PXB全称Percona XtraBackup,是Percona公司开源的MySQL热备软件。 支持无阻塞备份InnoDB和XtraDB引擎数据,在备份快结束时,还可以通过加短暂写锁备份MyISAM、Merge|和Archive引擎数据。
目前最新版本为2.4和8.0,对应MySQL 5.X和8.0。2.4版本不支持TockDB和MyRocks引擎。8.0.6增加支持MyRocks。
此外,PXB还有许多特性:增量备份,流压缩、在线移表,创建复制库,轻量级备份锁,IO限流,跳过二级索引,导出单个表等。

PXB工作原理

PXB备份是基于InnoDB的崩溃恢复机制。它直接拷贝你的InnoDB数据文件,这会导致内部数据不一致,但是之后它会对这些文件执行崩溃恢复,使它们重新成为一致、可用的数据库。
这一原理是因为InnoDB维护有一组redo日志,也叫事务日志,它包含了InnoDB数据每个变化的记录。当InnoDB启动时,会检查数据文件和事务日志,并进行两步操作,一是将已提交的事务日志写回数据文件,二是将未提交已经修改数据的事务进行回滚。
PXB启动时会记录日志序列号LSN,然后将数据文件复制走,复制需要一些时间,如果文件一直在变化,它们就会反映出不同时刻的数据库状态。同时,PXB会运行一个后台进程监视事务日志文件,并且复制变化 。因为事务日志是循环写入的,可以被复用,所以PXB需要持续不断的复制。PXB需要它开始运行后的所有数据文件变化的事务日志记录。
PXB使用轻量级备份锁来替代FTWRL,这一特性在Percona Server MySQL5.6+引入。它可以在复制非InnoDB数据量避免阻塞InnoDB表的DML操作。当MySQL支持备份锁时,xtrabackup会先复制InnoDB数据,运行lock tables for backup 并复制MyISAM表和.frm文件。一旦这些完成,它将备份.frm,.MGR,.MYD,.CSV,.par,.opt等文件。
之后,xtrabackup将使用lock binlog for backup锁来阻塞所有可能改变show master/slave stauts报告的binary log pos或 exec_master_log_pos或exec_gtid_set的操作。接着xtrabackup将完成复制redo日志文件和获取binary log点位。之后xtrabackup将释放binary log 和tables锁。
最后,binarylog点位将打印到STDERR,并且退出,如果一切正常则reture 0 。

在准备阶段,PXB使用复制的事务日志文件对数据文件执行崩溃恢复。完成后,数据库就准备好可以恢复并且使用了。
备份的MyISAM和InnoDB表将最终一致,因为在prepare阶段,InnoDB数据前滚到备份结束的时间点,不是回滚到开始时间点。这个时间点同FTWRL锁执行时间点是匹配的,因此MyISAM数据和准备好的(prepared)InnoDB数据是同步的。


还原备份

使用xtrabackup还原备份可以使用 xtrabackup --copy-back 或xtrabackup --move-back命令。
xtrabackup将从my.cnf读取datadir,innodb_data_home_dir,innodb_data_file_path,innodb_log_group_home_dir变量,并且检查目录是否存在。
它将先复制MyISAM表,索引等,然后InnoDB表和索引,最后日志文件。它将保持文件的属性,你可能需要在启动前修改属主为mysql,因为它们默认归属创建备份的用户。
作为选择,xtrabackup --move-back 选项也可用来还原备份。这一选项会删除备份文件,适用于没有足够磁盘空间时。


PXB安装 

PXB支持多种操作系统,有多种安装方式,这里以CentOS 7环境下载安装为例:

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpmyum localinstall percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpm


使用PXB,用户需要的最小权限:

GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';


PXB使用场景

PXB支持全备、增量备份、压缩备份、加密备份等。

使用PXB备份恢复大概包含三个步骤,创建备份、准备备份、恢复备份。

以全备为例

  1. 创建备份,文件夹不为空会报错,没有会自动创建。

    xtrabackup --backup --target-dir=/data/backups/

  2. 准备备份,版本大于等于创建时的版本,不要中断。

    xtrabackup --prepare --target-dir=/data/backups/

  3. 恢复备份,复制回恢复目录,记得修改owner 

    xtrabackup --copy-back --target-dir=/data/backups/


备份流程

根据备份日志及general日志,可以看到详细的备份流程。

备份流程(不支持备份锁)

  1. 启动,进行版本检查,连接MySQL,读取目录

  2. 启动一个后台进程,扫描复制redo log,持续进行

  3. 开始复制innodb表和数据文件

  4. 完成innodb表和数据文件复制,加锁FTWRL,阻塞所有修改操作

    FLUSH NO_WRITE_TO_BINLOG TABLES

    FLUSH TABLES WITH READ LOCK

  5. 开始复制非innodb表和文件

  6. 完成上一步,获取点位show master status

  7. 释放锁

    FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS

    UNLOCK TABLES

  8. 复制ib_buffer_pool,打印点位,写backup-my.cnf及lsn

  9. 最后completed OK!


备份流程(支持备份锁,比如PerconaServer for MySQL5.6+)

总体步骤同上,不同之处在于4-7步

  1. 启动,进行版本检查,连接MySQL,读取目录

  2. 启动一个后台进程,扫描复制redo log,持续进行

  3. 开始复制innodb表和数据文件

  4. 完成innodb表和数据文件复制,加备份表锁,不阻塞InnoDB表DML

    LOCK TABLES FOR BACKUP

  5. 开始复制非innodb表和文件

  6. 完成上一步,加binlog锁,LOCK BINLOG FOR BACKUP,获取点位show master status

  7. 释放锁

    FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS

    UNLOCK BINLOG

    UNLOCK TABLES

  8. 复制ib_buffer_pool,打印点位,写backup-my.cnf及lsn

  9. 最后completed OK!


关于Percona的备份锁

LOCK TABLES FOR BACKUP

    锁住非InnoDB表修改和所有DDL,InnoDB表可以DML。

LOCK BINLOG FOR BACKUP

    锁住binlog日志写入,阻止show master/slave status时点位或gtid改变,事务不提交可以执行DML。

FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS

    将缓存中的redo日志刷回磁盘,以保证能拷贝到。

UNLOCK BINLOG

    释放binlog锁。

UNLOCK TABLES

    释放表锁。


附:备份日志示例

[root@db-xxx ~]# innobackupex --defaults-file=/root/my3305.cnf --socket=/data/mysql_3305/mysql.sock /data/data_bakxtrabackup: recognized server arguments: --datadir=/data/mysql_3305 --server-id=111148 --log_bin=mysql-bin --tmpdir=/data/mysqltmpdir --innodb_buffer_pool_size=8G --innodb_file_per_table=1 --innodb_flush_log_at_trx_commit=1 --innodb_log_buffer_size=128M --innodb_log_file_size=512M --innodb_log_files_in_group=3 --innodb_flush_method=O_DIRECT --innodb_open_files=32768 --innodb_read_io_threads=8 --innodb_write_io_threads=8 --innodb_io_capacity=2000 xtrabackup: recognized client arguments: 220407 17:00:28 innobackupex: Starting the backup operation
IMPORTANT: Please check that the backup run completes successfully.At the end of a successful backup run innobackupex prints "completed OK!".
220407 17:00:28 version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;mysql_socket=/data/mysql_3305/mysql.sock' (using password: NO).220407 17:00:28 version_check Connected to MySQL server220407 17:00:28 version_check Executing a version check against the server...220407 17:00:28 version_check Done.220407 17:00:28 Connecting to MySQL server host: localhost, user: not set, password: not set, port: not set, socket: /data/mysql_3305/mysql.sockUsing server version 5.7.28-31-loginnobackupex version 2.4.24 based on MySQL server 5.7.35 Linux (x86_64) (revision id: b4ee263)xtrabackup: uses posix_fadvise().xtrabackup: cd to /data/mysql_3305xtrabackup: open files limit requested 0, set to 102400xtrabackup: using the following InnoDB configuration:xtrabackup: innodb_data_home_dir = .xtrabackup: innodb_data_file_path = ibdata1:12M:autoextendxtrabackup: innodb_log_group_home_dir = ./xtrabackup: innodb_log_files_in_group = 3xtrabackup: innodb_log_file_size = 536870912xtrabackup: using O_DIRECTInnoDB: Number of pools: 1220407 17:00:28 >> log scanned up to (2749841)xtrabackup: Generating a list of tablespacesInnoDB: Allocated tablespace ID 2 for mysql/plugin, old maximum was 0220407 17:00:29 >> log scanned up to (2749841)220407 17:00:30 [01] Copying ./ibdata1 to /data/data_bak/2022-04-07_17-00-28/ibdata1220407 17:00:30 [01] ...done220407 17:00:30 >> log scanned up to (2749841)220407 17:00:31 [01] Copying ./mysql/plugin.ibd to /data/data_bak/2022-04-07_17-00-28/mysql/plugin.ibd220407 17:00:31 [01] ...done...省略220407 17:00:33 Executing LOCK TABLES FOR BACKUP...220407 17:00:33 Starting to backup non-InnoDB tables and files220407 17:00:33 [01] Copying ./mysql/db.opt to /data/data_bak/2022-04-07_17-00-28/mysql/db.opt220407 17:00:33 [01] ...done...省略220407 17:00:37 Finished backing up non-InnoDB tables and files220407 17:00:37 Executing LOCK BINLOG FOR BACKUP...220407 17:00:37 [00] Writing /data/data_bak/2022-04-07_17-00-28/xtrabackup_binlog_info220407 17:00:37 [00] ...done220407 17:00:37 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...xtrabackup: The latest check point (for incremental): '2749873'xtrabackup: Stopping log copying thread..220407 17:00:37 >> log scanned up to (2749882)
220407 17:00:37 Executing UNLOCK BINLOG220407 17:00:37 Executing UNLOCK TABLES220407 17:00:37 All tables unlocked220407 17:00:37 [00] Copying ib_buffer_pool to /data/data_bak/2022-04-07_17-00-28/ib_buffer_pool220407 17:00:37 [00] ...done220407 17:00:37 Backup created in directory '/data/data_bak/2022-04-07_17-00-28/'MySQL binlog position: filename 'mysql-bin.000010', position '534', GTID of the last change '21973746-b571-11ec-b85c-fefcfe57c7ab:1-2,d35a24ba-b572-11ec-b3ba-fefcfe5f33ef:1-12'220407 17:00:37 [00] Writing /data/data_bak/2022-04-07_17-00-28/backup-my.cnf220407 17:00:37 [00] ...done220407 17:00:37 [00] Writing /data/data_bak/2022-04-07_17-00-28/xtrabackup_info220407 17:00:37 [00] ...donextrabackup: Transaction log of lsn (2749832) to (2749882) was copied.220407 17:00:37 completed OK!


附general日志

2022-04-07T17:00:28.867291+08:00 43 Connect root@localhost on using Socket2022-04-07T17:00:28.868227+08:00 43 Query SET SESSION wait_timeout=21474832022-04-07T17:00:28.869036+08:00 43 Query SELECT CONCAT(@@hostname, @@port)2022-04-07T17:00:28.871236+08:00 43 Quit 2022-04-07T17:00:28.875219+08:00 44 Connect root@localhost on using Socket2022-04-07T17:00:28.875460+08:00 44 Query SET SESSION wait_timeout=21474832022-04-07T17:00:28.875647+08:00 44 Query SET SESSION autocommit=12022-04-07T17:00:28.875823+08:00 44 Query SET NAMES utf82022-04-07T17:00:28.876023+08:00 44 Query SHOW VARIABLES2022-04-07T17:00:28.880405+08:00 44 Query SHOW ENGINE INNODB STATUS2022-04-07T17:00:28.907864+08:00 44 Query SELECT PLUGIN_NAME, PLUGIN_LIBRARY FROM information_schema.plugins WHERE PLUGIN_STATUS = 'ACTIVE' AND PLUGIN_TYPE = 'KEYRING'2022-04-07T17:00:28.909332+08:00 44 Query SELECTCONCAT(table_schema, '/', table_name), engineFROM information_schema.tablesWHERE engine NOT IN ('MyISAM', 'InnoDB', 'CSV', 'MRG_MYISAM')AND table_schema NOT IN ('performance_schema', 'information_schema', 'mysql')2022-04-07T17:00:33.243415+08:00 44 Query SET SESSION lock_wait_timeout=315360002022-04-07T17:00:33.243856+08:00 44 Query LOCK TABLES FOR BACKUP2022-04-07T17:00:37.481442+08:00 44 Query LOCK BINLOG FOR BACKUP2022-04-07T17:00:37.481793+08:00 44 Query SHOW MASTER STATUS2022-04-07T17:00:37.482095+08:00 44 Query SHOW VARIABLES2022-04-07T17:00:37.500022+08:00 44 Query FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS2022-04-07T17:00:37.707812+08:00 44 Query UNLOCK BINLOG2022-04-07T17:00:37.708174+08:00 44 Query UNLOCK TABLES2022-04-07T17:00:37.722529+08:00 44 Query SELECT UUID()2022-04-07T17:00:37.722916+08:00 44 Query SELECT VERSION()2022-04-07T17:00:37.953575+08:00 44 Quit


参考:

https://www.percona.com/doc/percona-xtrabackup/2.4/index.html