1. Xtrabackup工具安装
1. 系统环境说明
实验环境为CentOS 6.8,与其它Linux系统大同小异
2. 安装Xtrabackup
1)配置epel源:
[root@oldboy ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
---CentOS 7系统把epel源改成7的即可
2)安装Xtrabackup软件需要的基础环境包:
[root@oldboy ~]# yum install -y perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL
3)下载Xtrabackup软件并安装:
[root@oldboy ~]# wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
---如果地址无效,就去官网寻找合适的版本
[root@oldboy ~]# ll percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 8534624 Jul 21 2016 percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
[root@oldboy ~]# yum install -y percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm ---自动解决依赖包
4)查看安装后的结果:
[root@oldboy ~]# ll `which xtrabackup innobackupex`
lrwxrwxrwx. 1 root root 10 Apr 27 12:27 /usr/bin/innobackupex -> xtrabackup
-rwxr-xr-x. 1 root root 22136096 Jul 21 2016 /usr/bin/xtrabackup
2. Xtrabackup应用实践
1. 用于Xtrabackup数据备份的用户
用于Xtrabackup数据备份的用户也是需要一定权限的,具体配置如下(backup用户):
mysql> CREATE USER 'backup@localhost' IDENTIFIED BY 'backup123';
Query OK, 0 rows affected (0.03 sec)
mysql> GRANT RELOAD,LOCK TABLES,PROCESS,REPLICATION CLIENT ON *.* TO 'backup'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
此外,用于操作备份的Linux系统用户有读取和写入相关的目录的权限,一般情况下,还是建议使用root管理员权限进行备份,不管是MySQL还是Linux系统。
2. 用于恢复的MySQL配置文件
先创建存放MySQL日志文件的目录,将MySQL日志和数据文件分离到不同的目录中,以便于Xtrabackup恢复正式数据:
[root@oldboy ~]# mkdir /application/mysql/logs -p
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/logs
然后,修改MySQL的配置文件,把二进制日志、错误日志、慢查询日志从MySQL数据文件目录中迁移出来,并增加数据文件对应得目录。
[root@oldboy ~]# egrep -v "#|^$" /etc/my.cnf ---修改后的配置文件
[client]
user = root
password = oldboy123
[mysqld]
basedir = /application/mysql/ ---增加MySQL根目录
datadir = /application/mysql/data/ ---MySQL数据目录,Xtrabackup恢复数据时需要这个目录
---以下为binlog相关配置---
log_bin = /application/mysql/logs/oldboy-bin
expire_logs_days = 7
---以下为慢查询日志相关配置---
slow-query-log = ON
long_query_time = 2
log_queries_not_using_indexes = ON
slow-query-log-file = /application/mysql/logs/slow.log ---慢查询日志路径调整
min_examined_row_limit = 800
[mysqld_safe]
log-error = /application/mysql/logs/oldboy.err ---错误日志路径调整
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
调整完配置文件后重启MySQL
[root@oldboy ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.190427 13:03:52 mysqld_safe error: log-error set to '/application/mysql/logs/oldboy.err', however file don't exists. Create writable for user 'mysql'.
ERROR! The server quit without updating PID file (/application/mysql/data//oldboy.pid).
---重启时启动报错,提示修改配置文件后没有相关可写的错误日志文件,新建一个即可
[root@oldboy ~]# touch /application/mysql/logs/oldboy.err
[root@oldboy ~]# chown mysql.mysql !$
chown mysql.mysql /application/mysql/logs/oldboy.err
[root@oldboy ~]# ll !$
ll /application/mysql/logs/oldboy.err
-rw-r--r--. 1 mysql mysql 0 Apr 27 13:04 /application/mysql/logs/oldboy.err
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.... SUCCESS!
上面调整MySQL配置文件,是为了后面直接使用Xtrabackup(--copy-back)将数据文件还原到数据文件的目录中,如果使用mv等命令移动还原数据文件,则可以不调整对应配置文件参数。
3. Xtrabackup软件附带的备份工具说明
Xtrabackup软件主要包含两个常用的工具:
(1)Xtrabackup命令
Xtrabackup命令是专门用于对InnoDB和XtraDB等事务引擎得数据库热备份的工具,不能用于备份MyISAM等其他类型的引擎数据,其主要特点是备份数据时完全不用锁表。
(2)Innobackupex命令
Innobackupex命令是将上述Xtrabackup命令使用perl脚本进行二次封装的工具,除了可以用于InnoDB和XtraDB等引擎之外,还可以备份MyISAM及多种引擎混合使用的场景,该命令的主要特点是备份事务引擎数据而不用锁表,可以备份非事务引擎数据,但要锁表。
国内运维人员和DBA在企业里通常使用功能更多的Innobackupex命令来进行备份和恢复。
4. Innobackupex工具语法介绍
Innobackupex工具语法如下:
innobackupex [--user=name] [--host=name] [--password=WORD] [--port=PORT] [--socket=SOCKET] [--defaults-file=MY.CNF] PATH
5. 全备与恢复全备实践
5.1 数据准备
mysql> use oldboy
Database changed
mysql> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
+----+----------+
7 rows in set (0.00 sec)
5.2 开始全备
1)先创建一个规范的备份目录:
[root@oldboy backup]# mkdir /server/backup -p
执行备份时,屏幕会有非常多的输出信息,其实就是备份的工作流程细节,全备份与增量备份每当命令操作成功时,都会在日志的结尾处打印“completed ok!”作为标识:
[root@oldboy backup]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/full
---省略若干行提醒信息及读取数据库的innodb参数配置等
190427 17:58:46 >> log scanned up to (2010527) ---开始记录并监控redo日志
xtrabackup: Generating a list of tablespaces
InnoDB: Allocated tablespace ID 28 for oldboy/test, old maximum was 0
190427 17:58:47 [01] Copying ./ibdata1 to /server/backup/full/ibdata1
---开始复制innodb文件
190427 17:58:47 >> log scanned up to (2010527)
190427 17:58:48 [01] ...done
---省略若干行
190427 17:58:48 [01] Copying ./mysql/slave_worker_info.ibd to /server/backup/full/mysql/slave_worker_info.ibd
190427 17:58:48 [01] ...done
190427 17:58:48 Executing FLUSH NO_WRITE_TO_BINLOG TABLES...
190427 17:58:48 Executing FLUSH TABLES WITH READ LOCK... ---开始锁表备份非事务引擎表
190427 17:58:48 Starting to backup non-InnoDB tables and files
190427 17:58:48 [01] Copying ./oldboy/test.frm to /server/backup/full/oldboy/test.frm
190427 17:58:48 [01] ...done
---省略若干复制MyISAM表的数据文件行
190427 17:58:49 Finished backing up non-InnoDB tables and files
---备份非事务引擎表完成
190427 17:58:49 [00] Writing xtrabackup_binlog_info ---记录binlog位置
190427 17:58:49 [00] ...done
190427 17:58:49 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...
xtrabackup: The latest check point (for incremental): '2010527'
---记录最新的checkpoint
xtrabackup: Stopping log copying thread. ---停止日志监控进程
.190427 17:58:49 >> log scanned up to (2010527)
190427 17:58:49 Executing UNLOCK TABLES ---停止锁表
190427 17:58:49 All tables unlocked
---省略备份结果信息提示
190427 17:58:49 completed OK! ---备份成功的标识
最终的备份结果如下:
[root@oldboy ~]# ll /server/backup/full/
total 77860
-rw-r-----. 1 root root 418 Apr 27 17:58 backup-my.cnf ---配置文件备份
-rw-r-----. 1 root root 79691776 Apr 27 17:58 ibdata1 ---共享表空间备份
drwxr-x---. 2 root root 4096 Apr 27 17:58 mysql ---mysql库的备份
drwxr-x---. 2 root root 4096 Apr 27 17:58 oldboy ---oldboy库的备份
drwxr-x---. 2 root root 4096 Apr 27 17:58 oldboy_utf8 ------oldboy_utf8库的备份
drwxr-x---. 2 root root 4096 Apr 27 17:58 performance_schema ---performance_schema库的备份
-rw-r-----. 1 root root 22 Apr 27 17:58 xtrabackup_binlog_info ---binlog的位置信息
-rw-r-----. 1 root root 113 Apr 27 17:58 xtrabackup_checkpoints ---checkpoints信息
-rw-r-----. 1 root root 569 Apr 27 17:58 xtrabackup_info ---xtrabackup信息
-rw-r-----. 1 root root 2560 Apr 27 17:58 xtrabackup_logfile ---xtrabackup日志文件
[root@oldboy ~]# cd /server/backup/full/
[root@oldboy full]# cat xtrabackup_binlog_info
oldboy-bin.000001 120 ---binlog位置信息
[root@oldboy full]# cat xtrabackup_checkpoints ---存放备份的起始位置和结束位置
backup_type = full-backuped ---备份类型
from_lsn = 0 ---checkpoints起始点
to_lsn = 2010527 ---checkpoints结束点
last_lsn = 2010527
compact = 0
recover_binlog_info = 0
5.3 利用全备恢复数据
使用Innobackupex备份的数据有可能会处于不一致的状态,因此在恢复数据之前,首先要将数据调成一致性的状态,即需要应用备份过程中记录变化的日志(xtrabackup_logfile),同时回滚未提交的事务日志数据:
[root@oldboy full]# innobackupex --apply-log --use-memory=32M /server/backup/full/
提示:
1)“--apply-log”用于记录变化的日志,并回滚未提交得事务日志数据
2)“use-memory=32M”是分配的使用内存大小
执行完此命令之后,备份的数据就可以用来恢复了。
使用Xtrabackup备份的本质就是复制物理数据文件,因此,在进行最终恢复时,需要临时关闭数据库,把物理文件复制回去进行恢复:
[root@oldboy ~]# /etc/init.d/mysqld stop ---先停库
Shutting down MySQL.. SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /application/mysql/data_ori ---模拟删除数据文件
[root@oldboy ~]# mkdir -p /application/mysql/data ---创建原始数据目录,目录要为空
[root@oldboy ~]# mv /server/backup/full/* /application/mysql/data/ ---使用mv直接复制更舒服一些
---也可以使用下面的命令复制还原数据,和mv命令的功能是一样的,下面的命令的缺点是要根据MySQL配置文件的路径进行回拷贝,因此
配置文件没有指定数据文件路径、数据文件目录不为空等,都会导致无法回拷贝的问题。命令如下:
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /server/backup/full/
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data
---如果权限不对,启动数据库可能会报“Starting MySQL. ERROR! The server quit without updating PID file”错误
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;" ---恢复成功
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
+----+----------+
6. 增量备份与恢复增量数据实践
使用Xtrabackup程序做增量备份之前,首先要进行一次全备份,第一次增量备份是基于全备进行的,之后的每一次增量备份都会基于上一次增量备份的数据来实现,操作如下:
(1)创建基础全备份
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/base_full
(2)模拟增加数据,然后做增量备份
增加如下数据:
mysql> use oldboy
Database changed
mysql> insert into test values(8,'outman');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(9,'outgirl');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
| 8 | outman | ---全备后模拟增加了以下两行数据
| 9 | outgirl |
+----+----------+
9 rows in set (0.00 sec)
开始做第一次增量备份:
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --incremental-basedir=/server/backup/base_full --incremental /server/backup/one_inc
注意,这里指定的全备路径是--incremental-basedir=/server/backup/base_full。
增量备份的结果在/server/backup/one_inc下,其实就是从全备信息里最后得LSN开始读取redo数据,对改变的数据进行增量备份,所以我们刚刚增加的增量数据很少,InnoDB数据文件备份得也很少,增量备份的InnoDB数据备份的关键输出如下:
xtrabackup: using the full scan for incremental backup
190427 21:55:43 [01] Copying ./ibdata1 to /server/backup/one_inc/ibdata1.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./oldboy/test.ibd to /server/backup/one_inc/oldboy/test.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/innodb_index_stats.ibd to /server/backup/one_inc/mysql/innodb_index_stats.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/innodb_table_stats.ibd to /server/backup/one_inc/mysql/innodb_table_stats.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_master_info.ibd to /server/backup/one_inc/mysql/slave_master_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_relay_log_info.ibd to /server/backup/one_inc/mysql/slave_relay_log_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_worker_info.ibd to /server/backup/one_inc/mysql/slave_worker_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:44 >> log scanned up to (2017505)
---省略无用行---
190427 21:55:45 [00] Writing xtrabackup_info
190427 21:55:45 [00] ...done
xtrabackup: Transaction log of lsn (2017505) to (2017505) was copied.
190427 21:55:45 completed OK!
根据输出,我们也大概了解了插入数据到数据库时,对数据库会有什么影响,面对于非事务引擎的备份,则仍是锁表进行全备。
(3)再模拟增加的数据,然后做第二次增量备份
增加如下数据:
mysql> use oldboy
Database changed
mysql> insert into test values(10,'two_inc1');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(11,'two_inc2');
Query OK, 1 row affected (0.00 sec)
开始做第二次增量备份,注意,这里要用到第一次增量备份的目录,而不是全备目录:
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --parallel=3 --incremental-basedir=/server/backup/one_inc/ --incremental /server/backup/two_inc
到此为止,已经完成了1次全备,以及全备之后的两次增量数据备份
(4)开始做增量数据恢复
增量恢复的步骤为先恢复全备(base_full目录)数据,然后再恢复第一次增量(one_inc)的数据,以及第二次增量(two_inc)的数据,如果有更多次增量备份就以此类推。
1)应用redo日志恢复全备数据:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only /server/backup/base_full/
注意:非最后一次合并增量数据一定要加--redo-only参数,即只应用redo日志恢复数据,而不执行undo回滚未提交的数据,等到最后一次增量备份合并完成后再进行undo日志回滚数据。
2)合并第一次的增量数据到全备数据目录:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only --incremental-dir=/server/backup/one_inc /server/backup/base_full/
3)合并第二次的增量数据到全备数据目录:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --incremental-dir=/server/backup/two_inc /server/backup/base_full/
需要强调的是,最后一次合并增量数据到全备时,取消了“redo-only”参数。
4)对最终的全量数据做redo日志应用,并执行undo回滚数据:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M /server/backup/base_full/
提示:本命令取消了“--redo-only”参数,目的是应用undo日志回滚数据,为最终的恢复数据做准备。
5)开始正式恢复数据:
[root@oldboy ~]# /etc/init.d/mysqld stop
Shutting down MySQL.... SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /tmp/data_ori1
[root@oldboy ~]# mkdir -p /application/mysql/data ---原始数据目录要为空
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /server/backup/base_full/
---看看innobackupex效果和mv是不是一样
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
| 8 | outman |
| 9 | outgirl |
| 10 | two_inc1 |
| 11 | two_inc2 |
+----+----------+
到此为止,全量和后增加的增量数据就都回来了,但上述恢复还未涉及binlog恢复的情况,因此,在实际生产中仅仅用上述方法来恢复数据,得到的数据将是不完整的,还需要进行binlog文件的恢复才行。
7. 中小企业MySQL Xtrabackup物理增量恢复案例实战
什么样的条件才能完整地物理恢复数据库数据?
- 具备全量备份(Xtrabackup备份的全备)
- 具备全量之后的所有增量备份(Xtrabackup备份的增量)
- 具备最后一次增量备份以后的所有MySQL的binlog增量日志
假设当前数据库内的数据如下:
mysql> use oldboy
Database changed
mysql> truncate table test;
Query OK, 0 rows affected (0.05 sec)
mysql> insert into test values(1,'full01');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(2,'full02');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(3,'full03');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(4,'full04');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(5,'full05');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+----+--------+
| id | name |
+----+--------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
+----+--------+
5 rows in set (0.00 sec)
先模拟5月3日0点开始对数据库oldboy数据进行全备:
[root@oldboy ~]# date -s "2019/05/03"
Fri May 3 00:00:00 CST 2019
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/new_base_full
然后模拟5月3日0点全备之后(0:00-24:00点)用户继续写入数据:
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(6,'new_inc_one_1');"
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(7,'new_inc_one_2');"
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
+----+---------------+
之后,在5月4日0点做增量备份(没做全备):
[root@oldboy ~]# date -s "2019/05/04"
Sat May 4 00:00:00 CST 2019
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --incremental-basedir=/server/backup/new_base_full/ --incremental /server/backup/new_one_inc
在5月4日0点增备之后(0:00-24:00)用户继续写入数据:
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(8,'binlog_data_1');"
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(9,'binlog_data_2');"
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 |
| 9 | binlog_data_2 |
+----+---------------+
假设5月4日上午10:00点管理人员误删除了oldboy数据库:
[root@oldboy ~]# date -s "2019/05/04 10:00"
Sat May 4 10:00:00 CST 2019
[root@oldboy ~]# mysql -e "drop database oldboy;show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| oldboy_utf8 |
| performance_schema |
+--------------------+
数据库出问题10分钟后,公司的网站运营人员报网站故障,联系运维人员、DBA解决。此时,DBA或开发人员会查看网站报错(或者查看后台日志),可以看到连不上oldboy数据库的提示,然后登陆数据库排查,发现数据库oldboy已经不存在了。登陆系统分析系统审计日志,以及分析数据库binlog也可以发现库丢失的原因;开发人员通过程序日志判断应该也可以查出来原因。
开始进行恢复前的准备:
1)移走所有binlog增量文件,防止被二次破坏
[root@oldboy ~]# cp -a /application/mysql/logs /server/backup/binlog
2)开始恢复数据前的增量备份和全备合并
先合并全备数据到新全备目录,即恢复第一天0点前的所有数据:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only /server/backup/new_base_full/
再合并增量数据到新全备目录,即恢复第二天0点前的所有数据:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --incremental-dir=/server/backup/new_one_inc/ /server/backup/new_base_full/
最后应用所有redo日志,并回滚未提交的数据:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M /server/backup/new_base_full/
3)开始恢复binlog日志数据
由于5月4日0点之后的所有数据并不在全备里,也不在增量里,而是在MySQL的binlog日志里,因此还要进行如下操作来完成恢复。
首先查看5月4日0点最后一次增量的binlog位置信息:
[root@oldboy ~]# cat /server/backup/new_one_inc/xtrabackup_binlog_info
oldboy-bin.000003 1820
这个位置信息以后的binlog才是我们需要的,以前的数据在Xtrabackup的全量和增量里已经有了,然后查看问题出现后第一时间备份的binlog文件信息:
[root@oldboy ~]# ll /server/backup/binlog/oldboy-bin.*
-rw-rw----. 1 mysql mysql 143 Apr 27 21:16 /server/backup/binlog/oldboy-bin.000001
-rw-rw----. 1 mysql mysql 1951 Apr 27 23:17 /server/backup/binlog/oldboy-bin.000002
-rw-rw----. 1 mysql mysql 2386 May 4 10:00 /server/backup/binlog/oldboy-bin.000003
-rw-rw----. 1 mysql mysql 126 Apr 27 23:21 /server/backup/binlog/oldboy-bin.index
从上面的信息可知,需要使用的binlog文件为oldboy-bin.000003。(因为最后面就是oldboy-bin.000003了)
现在从oldboy-bin.000003文件的1820位置点开始恢复增量数据:
[root@oldboy binlog]# mysqlbinlog -d oldboy oldboy-bin.000003 --start-position=1820 -r bin.sql
这里要剔除误删除数据库的drop语句,否则,直接恢复就又进入了删库故障的坑:
[root@oldboy binlog]# grep -w drop bin.sql ---找出误删除数据库的语句
drop database oldboy
[root@oldboy binlog]# sed -i '/drop database oldboy/d' bin.sql ---剔除误删除数据库的drop语句
[root@oldboy binlog]# grep -w drop bin.sql
需要注意的是,本案例是删除数据库了,因此binlog日志就不再增长了,所以可以利用上文第一时间备份的binlog恢复,如果是update操作误改了数据又没有停库,那么,此时最好是在数据库服务器上用Iptables控制应用程序连接数据库之后,再从上述binlog位置点开始读取正式日志目录下的所有binlog日志,一直将Iptables限制访问时的所有binlog日志恢复完。
下面开始正式恢复数据库数据。
1)停止数据库对外访问。因为是使用drop命令删除库,而且后面不会有写入了,所以可以不用额外停止写入,但如果是update导致的数据破坏,那么最好是在发现问题的第一时间就进行停库处理或对外停止写入。
[root@oldboy ~]# iptables -I INPUT -p tcp --dport 3306 ! -s 192.168.9.115 -j DROP ---非192.168.9.115禁止访问数据库3306端口
2)恢复处理好的Xtrabackup备份的全量及增量数据:
[root@oldboy ~]# /etc/init.d/mysqld stop ---恢复时要停库
Shutting down MySQL.. SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /tmp/data3 ---移走旧的数据
[root@oldboy ~]# mkdir -p /application/mysql/data ---原始数据目录要为空
[root@oldboy ~]# mv /server/backup/new_base_full/* /application/mysql/data/
---采用mv,而不是xtrabackup的--copy-back参数还原,使用mv的时候,前文的MySQL配置就可以采用了
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data/ ---重新授权
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
+----+---------------+
到此,使用Xtrabackup备份的到5月3日的全备数据和5月4日0点之前增量备份的数据都回来了。
接下来开始恢复5月4日0点到10点的数据库数据。
这时需要恢复binlog数据,即从binlog解析出数据并且清理了drop语句的bin.sql文件:
[root@oldboy ~]# cd /server/backup/binlog/
[root@oldboy binlog]# mysql oldboy < bin.sql
[root@oldboy binlog]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 | ---binlog里记录的数据回来了
| 9 | binlog_data_2 |
+----+---------------+
到此,恢复完毕。
8. 使用Xtrabackup物理分库分表备份
使用Xtrabackup物理分库分表备份的前提是开启独立表空间模式,即设置innodb_file_per_table=On,MySQL5.6默认已经开启了此模式。
1)备份单个库oldboy:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --database="oldboy" /server/backup/oldboy_full
[root@oldboy binlog]# ll /server/backup/oldboy_full/
total 77860
-rw-r-----. 1 root root 418 May 4 12:52 backup-my.cnf
-rw-r-----. 1 root root 79691776 May 4 12:52 ibdata1
drwxr-x---. 2 root root 4096 May 4 12:52 mysql
drwxr-x---. 2 root root 4096 May 4 12:52 oldboy
drwxr-x---. 2 root root 4096 May 4 12:52 oldboy_utf8
drwxr-x---. 2 root root 4096 May 4 12:52 performance_schema
-rw-r-----. 1 root root 22 May 4 12:52 xtrabackup_binlog_info
-rw-r-----. 1 root root 113 May 4 12:52 xtrabackup_checkpoints
-rw-r-----. 1 root root 593 May 4 12:52 xtrabackup_info
-rw-r-----. 1 root root 2560 May 4 12:52 xtrabackup_logfile
2)备份多个库:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy oldgirl" /server/backup/oldboy_oldgirl
[root@oldboy binlog]# ll /server/backup/oldboy_oldgirl/
total 77848
-rw-r-----. 1 root root 418 May 4 12:55 backup-my.cnf
-rw-r-----. 1 root root 79691776 May 4 12:55 ibdata1
drwxr-x---. 2 root root 4096 May 4 12:55 oldboy
drwxr-x---. 2 root root 4096 May 4 12:55 oldgirl
-rw-r-----. 1 root root 22 May 4 12:55 xtrabackup_binlog_info
-rw-r-----. 1 root root 113 May 4 12:55 xtrabackup_checkpoints
-rw-r-----. 1 root root 606 May 4 12:55 xtrabackup_info
-rw-r-----. 1 root root 2560 May 4 12:55 xtrabackup_logfile
3)备份单个表:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test" /server/backup/oldboy_test
4)备份多个库的多个表:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test oldboy.student" /server/backup/oldboy_test_student
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test oldboy.student mysql.user" /server/backup/all
9. 使用Xtrabackup物理分库分表备份的恢复
在使用Xtrabackup物理分库分表备份的恢复时,需要使用“--export”来做恢复准备,最终恢复时,不能使用常规的“--copy-back”选项,而是要初始化一个带有mysql库(“mysql_install_db --user=mysql”)的干净的数据文件目录。
1)恢复准备
[root@oldboy binlog]# innobackupex --apply-log --export /server/backup/oldboy_test/ ---恢复oldboy的test表
2)初始化数据库(这里为了方便,直接在当前环境测试)
[root@oldboy binlog]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS!
[root@oldboy binlog]# mv /application/mysql/data /tmp/data.ori ---备份前面的数据
[root@oldboy binlog]# mkdir /application/mysql/data
[root@oldboy binlog]# /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/application/mysql/data --user=mysql ---初始化新的mysql数据文件
[root@oldboy binlog]# cp /server/backup/oldboy_test/* /application/mysql/data/
[root@oldboy binlog]# chown -R mysql.mysql /application/mysql/data
[root@oldboy binlog]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
mysql> select * from oldboy.test; ---查看还原的数据
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 |
| 9 | binlog_data_2 |
+----+---------------+
9 rows in set (0.00 sec)
如果有需要,可以通过mysqldump导出后恢复到正式库
最后把当前的环境恢复回来:
[root@oldboy binlog]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS!
[root@oldboy binlog]# mv /application/mysql/data /opt/data.new
[root@oldboy binlog]# mv /tmp/data.ori /application/mysql/data
[root@oldboy binlog]# chown -R mysql.mysql /application/mysql/data
[root@oldboy binlog]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!