MySQL的XtraBackup进行备份和恢复(全备+增备+binlog)

XtraBackup的全备份+XtraBackup增量备份+binlog日志进行恢复最新数据。也可以恢复误操作。

刚开始用mysqldump,备份100G+的数据库,再加上服务器繁忙,备份速度像蜗牛似的,于是寻找更高效的备份方法。

Xtrabackup备份原理:

物理备份,不锁表,那么怎么保证现有的数据(备份过程中有尚未提交或已经提交但未同步事务)与复制出来的数据一致呢?

我们知道MySQL修改操作都会先记录在ib_logfile日志文件,再同步到磁盘,这个文件并重复使用。在复制期间会开启一个线程用来监控ib_logfile日志文件,如果有修改就从上次记录的日志序列号(checkpoins)开始复制新增内容到Logfile文件。复制结束后,把logfile事务日志进行回滚,把未完成的事务同步到ibdata1和ibd里面,来保证数据一致性。这与Mysql崩溃后恢复基本操作一样

1.1 了解备份方式

热备份:读写不受影响(mysqldump-->innodb)

温备份:仅可以执行读操作(mysqldump-->myisam)

冷备份:离线备份,读写都不可用

逻辑备份:将数据导出文本文件中(mysqldump)

物理备份:将数据文件拷贝(xtrabackup、mysqlhotcopy)

完整备份:备份所有数据

增量备份:仅备份上次完整备份或增量备份以来变化的数据

差异备份:仅备份上次完整备份以来变化的数据

1.3 安装方式

CentOS:

# rpm -ivh http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm

# yum install percona-xtrabackup #xtrabackup2.2不支持MySQL5.1的Innodb引擎,如需要可安装2.0版本(https://www.percona.com/downloads/XtraBackup/XtraBackup-2.0.8/RPM/rhel6/x86_64/percona-xtrabackup-20-2.0.8-587.rhel6.x86_64.rpm)

1.4 了解常用参数

--user= #指定数据库备份用户

--password= #指定数据库备份用户密码

--port= #指定数据库端口

--host= #指定备份主机

--socket= #指定socket文件路径

--databases= #备份指定数据库,多个空格隔开,如--databases="dbname1 dbname2",不加备份所有库

--defaults-file= #指定my.cnf配置文件

--apply-log #日志回滚

--incremental= #增量备份,后跟增量备份路径

--incremental-basedir= #增量备份,指上次增量备份路径

--redo-only #合并全备和增量备份数据文件

--copy-back #将备份数据复制到数据库,数据库目录要为空

--no-timestamp #生成备份文件不以时间戳为目录名

--stream= #指定流的格式做备份,--stream=tar,将备份文件归档

--remote-host=user@ip DST_DIR #备份到远程主机

使用xtrabackup进行MySQL数据库备份

前面介绍mysqldump备份方式是采用逻辑备份,其最大的缺陷就是备份和恢复速度都慢,对于一个小于50G的数据库而言,这个速度还是能接受的,但如果数据库非常大,那再使用mysqldump备份就不太适合了。而使用lvm快照功能对数据库进行备份,可以实现几乎热备的功能,但备份过程较为复杂,不过现在倒是有个工具mylvmbackup可以实现自动化备份。

前面我们也说道,使用物理备份时最快的,那有没有办法实现物理热备呢?

目前主流的有两个工具可以实现热备:ibbackup和xtrabackup;ibbackup是商业软件,没服务器授权为5000美元,非常昂贵。而xtrabackup功能比ibbackup还要强大,但却是开源的。因此我们这里就来介绍xtrabackup的使用。

Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具。特点:

  • (1)备份过程快速、可靠;
  • (2)备份过程不会打断正在执行的事务;
  • (3)能够基于压缩等功能节约磁盘空间和流量;
  • (4)自动实现备份检验;
  • (5)还原速度快;

Xtrabackup中主要包含两个工具:

xtrabackup:是用于热备份innodb, xtradb表中数据的工具,不能备份其他类型的表,也不能备份数据表结构,xtrabackup命令只备份数据文件,并不备份数据表结构(.frm),所以使用xtrabackup恢复的时候必须有对应表结构文件(.frm)。用innobackupex命令,此命令相当于冷备份,复制数据目录的索引,数据,结构文件,但会有短暂的锁表(时间依赖于MyISAM大小)。;

innobackupex:是将xtrabackup进行封装的perl脚本,提供了备份myisam表的能力。

开始使用xtarbackup进行备份:参数按照要备份的数据库信息填写.--defaults-file=/etc/my.cnf参数必须要放在第一个参数,不然会报错,host参数和user参数要根据MySQL数据库中的user表信息配置不然会连接不上MySQL服务器。

查看要备份的数据库的信息:

[root@localhost104 opt]# ps -ef | grep mysql root 12567 1 0 Jul27 ? 00:00:00 /bin/sh /usr/local/mysql//bin/mysqld_safe --datadir=/usr/local/mysql/data/ --pid-file=/usr/local/mysql/mysql.pid mysql 12854 12567 0 Jul27 ? 00:01:58 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/mysql_safe.log --pid-file=/usr/local/mysql/mysql.pid --socket=/usr/local/mysql/mysql.sock --port=3306

创建全备份的目录并给相应的用户权限和属组

[root@localhost104 opt]# mkdir /opt/xtrabackup_full [root@localhost104 opt]# chmod 700 /opt/xtrabackup_full

#全备份

[root@localhost 2017-07-29_14-05-49]# which xtrabackup /usr/bin/xtrabackup

[root@localhost104 opt]# innobackupex --defaults-file=/etc/my.cnf --user='root' --password='123456' --host='localhost' --port=3306 --socket='/usr/local/mysql/mysql.sock' --parallel=3 /opt/xtrabackup_full

........

170729 12:54:48 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS... xtrabackup: The latest check point (for incremental): '20125155' xtrabackup: Stopping log copying thread. .170729 12:54:48 >> log scanned up to (20125164) 170729 12:54:49 Executing UNLOCK TABLES 170729 12:54:49 All tables unlocked 170729 12:54:49 [00] Copying ib_buffer_pool to /opt/xtrabackup/2017-07-29_12-54-44/ib_buffer_pool 170729 12:54:49 [00] ...done 170729 12:54:49 Backup created in directory '/opt/xtrabackup/2017-07-29_12-54-44/' MySQL binlog position: filename 'mysql_bin.000414', position '154' 170729 12:54:49 [00] Writing /opt/xtrabackup/2017-07-29_12-54-44/backup-my.cnf 170729 12:54:49 [00] ...done 170729 12:54:49 [00] Writing /opt/xtrabackup/2017-07-29_12-54-44/xtrabackup_info 170729 12:54:49 [00] ...done xtrabackup: Transaction log of lsn (20125155) to (20125164) was copied. 170729 12:54:49 completed OK!

备份后的文件:

在备份的同时,备份数据会在备份目录下创建一个以当前日期时间为名字的目录存放备份文件:

[root@localhost 2017-07-29_12-34-51]# pwd

/opt/xtrabackup/2017-07-29_12-34-51

[root@localhost 2017-07-29_12-34-51]# ll

total 77876

-rw-r----- 1 root root 425 Jul 29 12:34 backup-my.cnf

-rw-r----- 1 root root 546 Jul 29 12:34 ib_buffer_pool

-rw-r----- 1 root root 79691776 Jul 29 12:34 ibdata1

drwxr-x--- 2 root root 4096 Jul 29 12:34 mysql

drwxr-x--- 2 root root 8192 Jul 29 12:34 performance_schema

drwxr-x--- 2 root root 8192 Jul 29 12:34 sys

drwxr-x--- 2 root root 146 Jul 29 12:34 testdb

-rw-r----- 1 root root 21 Jul 29 12:34 xtrabackup_binlog_info

-rw-r----- 1 root root 115 Jul 29 12:34 xtrabackup_checkpoints

-rw-r----- 1 root root 566 Jul 29 12:34 xtrabackup_info

-rw-r----- 1 root root 2560 Jul 29 12:34 xtrabackup_logfile

各文件说明:

[root@localhost 2017-07-29_12-34-51]# cat xtrabackup_binlog_info mysql_bin.000414 154

记录备份的类型、开始和结束的日志序列号 [root@localhost 2017-07-29_12-34-51]# cat xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 20125155 last_lsn = 20125164 compact = 0 recover_binlog_info = 0

[root@localhost 2017-07-29_12-34-51]# cat xtrabackup_info uuid = 45d5fa84-7417-11e7-bdad-000c297442b7 name = tool_name = innobackupex tool_command = --defaults-file=/etc/my.cnf --user=root --password=... --host=localhost --port=3306 --socket=/usr/local/mysql/mysql.sock --parallel=3 /opt/xtrabackup tool_version = 2.4.8 ibbackup_version = 2.4.8 server_version = 5.7.18-log start_time = 2017-07-29 12:34:52 end_time = 2017-07-29 12:34:56 lock_time = 0 binlog_pos = filename 'mysql_bin.000414', position '154' innodb_from_lsn = 0 innodb_to_lsn = 20125155 partial = N incremental = N format = file compact = N compressed = N encrypted = N

(1)xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

(3)xtrabackup_binlog_pos_innodb —— 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf —— 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

另外还需注意:备份数据库的用户需要具有相应权限,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:grant us

grant user 'bkpuser'@'localhost' identified by '123';

grant reload,lock tables,replication client on *.* to 'bkpuser'@'localhost';

flush privileges;

(三)增量备份

创造第一个增量数据表xtrabackup_increment_1_t

mysql> create table testdb.xtrabackup_increment_1_t(id int,name varchar(20)); Query OK, 0 rows affected (0.32 sec) mysql> show tables; +--------------------------+ | Tables_in_testdb | +--------------------------+ | add_data1 | | add_data2 | | student_t | | xtrabackup_increment_1_t | +--------------------------+ 4 rows in set (0.00 sec) mysql> insert into xtrabackup_increment_1_t values(1,'anzhen'),(2,'anzhu'); Query OK, 2 rows affected (0.09 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from testdb.xtrabackup_increment_1_t; +------+--------+ | id | name | +------+--------+ | 1 | anzhen | | 2 | anzhu | +------+--------+ 2 rows in set (0.03 sec)

创建增量备份目录

[root@localhost opt]# mkdir -p /opt/xtrabackup_increment [root@localhost opt]# chmod 700 /opt/xtrabackup_increment

增量备份命令1: 注意:第一次执行增备的时候--incremental-basedir这个参数是填写最近一次全备的目录做为增备的基础目录

[root@localhost opt]# innobackupex --defaults-file=/etc/my.cnf --user='root' --password='123456' --socket='/usr/local/mysql/mysql.sock' --port=3306 --incremental --incremental-basedir='/opt/xtrabackup_full/2017-07-29_12-34-51/' --parallel=3 /opt/xtrabackup_increment

#指定上次完整备份目录

如果有completed OK!说明增量备份成功!

xtrabackup: Transaction log of lsn (20132701) to (20132710) was copied.

170729 14:05:57 completed OK!

查看相关全备份信息:

[root@localhost104 2017-07-29_12-54-44]# cat xtrabackup_binlog_info mysql_bin.000414 154 [root@localhost104 2017-07-29_12-54-44]# cat xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 20125155 last_lsn = 20125164 compact = 0 recover_binlog_info = 0 [root@localhost104 2017-07-29_12-54-44]# pwd /opt/xtrabackup_full/2017-07-29_12-54-44

说明全备份的最后一个日志文件是mysql_bin.000414,位置是154,from_lsn 来自的日志号为0,to_lsn = 20125155。下个增量备份要用到这个to_lsn = 20125155。才可以全备和曾备连接起来。

查看相关增量备份信息:

[root@localhost 2017-07-29_14-05-49]# cat xtrabackup_binlog_info mysql_bin.000414 667 [root@localhost 2017-07-29_14-05-49]# cat xtrabackup_binlog_info mysql_bin.000414 667 [root@localhost 2017-07-29_14-05-49]# cat xtrabackup_checkpoints backup_type = incremental from_lsn = 20125155 to_lsn = 20132701 last_lsn = 20132710 compact = 0 recover_binlog_info = 0 [root@localhost 2017-07-29_14-05-49]# pwd /opt/xtrabackup_increment/2017-07-29_14-05-49

说明增备份的最后一个日志文件是mysql_bin.000414,位置是667,from_lsn 来自的日志号为20125155,也就是最近一次全部或者增备的to_lsn号。这次增备为to_lsn = 20132701。

信息如下:

170729 14:24:04 [00] Writing /opt/xtrabackup_increment/2017-07-29_14-23-44/xtrabackup_info 170729 14:24:04 [00] ...done xtrabackup: Transaction log of lsn (20139866) to (20139875) was copied. 170729 14:24:05 completed OK!

记录了lsn号的备份信息。OK就成功!

(四)误操作

mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | testdb | +--------------------+ 5 rows in set (0.16 sec) mysql> drop database testdb; Query OK, 6 rows affected (0.82 sec) mysql> commit; Query OK, 0 rows affected (0.02 sec)

mysql> flush logs; Query OK, 0 rows affected (0.05 sec)

mysql> create database test_new; Query OK, 1 row affected (0.00 sec)

mysql> create table test_new.xtrabackup_increment_4_t(id int,name varchar(20)); Query OK, 0 rows affected (0.10 sec) mysql> insert into test_new.xtrabackup_increment_4_t values(32,'3zhen'),(242,'asfwthu'); Query OK, 2 rows affected (0.09 sec)

mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from test_new.xtrabackup_increment_4_t; +------+---------+ | id | name | +------+---------+ | 32 | 3zhen | | 242 | asfwthu | +------+---------+ 2 rows in set (0.00 sec)

mysql> flush logs;

(四)全备恢复和增备恢复。现在要恢复四个xtrabackup_increment_4_t 数据表的数据和误操作的数据

4.1 停掉MySQL服务

[root@localhost104 mysql]# ps -ef | grep mysql root 12567 1 0 Jul27 ? 00:00:00 /bin/sh /usr/local/mysql//bin/mysqld_safe --datadir=/usr/local/mysql/data/ --pid-file=/usr/local/mysql/mysql.pid mysql 12854 12567 0 Jul27 ? 00:02:08 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/mysql_safe.log --pid-file=/usr/local/mysql/mysql.pid --socket=/usr/local/mysql/mysql.sock --port=3306 root 48441 48401 0 13:53 pts/3 00:00:00 mysql -uroot -p root 49567 45091 0 15:45 pts/1 00:00:00 grep --color=auto mysql [root@localhost104 mysql]# [root@localhost104 mysql]# [root@localhost104 mysql]# cd /usr/local/mysql/

[root@localhost104 support-files]# ls

magic mysqld_multi.server mysql-log-rotate mysql.server [root@localhost104 support-files]# ./mysql.server stop Shutting down MySQL...... SUCCESS! [root@localhost104 support-files]# ps -ef | grep mysql root 48441 48401 0 13:53 pts/3 00:00:00 mysql -uroot -p root 49614 45091 0 15:46 pts/1 00:00:00 grep --color=auto mysql

#把原来的MySQL数据目录进行重命名,保留原来的binlog二进制文件,用于恢复最新数据。

[root@localhost104 mysql]#cd /usr/local/mysql

[root@localhost104 mysql]#mv /usr/local/mysql/data /usr/local/mysql/data_bak

[root@localhost104 mysql]#mkdir /usr/local/mysql/data

[root@localhost104 mysql]#chown mysql:mysql /usr/local/mysql/data

4.2准备(prepare)一个完全备份

建完备份之后数据被没有马上可以被还原,需要回滚未提交事务,前滚提交事务,让数据库文件保持一致性。

innobackupex使用—apply-log来做预备备份。

一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:--use-memory=4G指定使用的内存,按内存的大小分配,这样可以加快恢复的速度。

xtrabackup把备份过程中可能有尚未提交的事务或已经提交但未同步数据文件的事务,写到xtrabackup_logfile文件,所以要先通过这个日志文件回滚,把未完成的事务同步到备份文件,保证数据文件处于一致性。

[root@localhost 2017-07-29_12-34-51]# pwd /opt/xtrabackup/2017-07-29_12-34-51 [root@localhost 2017-07-29_12-34-51]#innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only /opt/xtrabackup_full/2017-07-29_12-34-51 --use-memory=4G --user=root --password=123456 如果执行正确,其最后输出的几行信息通常如下:

xtrabackup: starting shutdown with innodb_fast_shutdown = 1

xtrabackup: This target seems to be not prepared yet.

InnoDB: FTS optimize thread exiting. InnoDB: Starting shutdown... InnoDB: Shutdown completed; log sequence number 20125736 170729 13:30:29 completed OK!

成功后,备份可以被用来还原数据库了

看到redo log已经出现。xtrabackup_开头的几个文件记录了一些日志偏移量的信息和日志名和时间等信息。在xtrabackup_checkpoints中记录了备份的模式:

backup_type = full-backuped。

xtrabackup_binlog_info:记录当前最新的LOG Positionxtrabackup_binlog_pos_innodb:innodb log postionxtrabackup_checkpoints: 存放备份的起始位置beginlsn和结束位置endlsn,增量备份需要这个lsn[增量备份可以在这里面看from和to两个值的变化xtrabackup_info:备份的一些具体信息日志

四个增量表已经恢复到新的数据目录了。

4.5 修改数据目录的权限

[root@localhost testdb]#chown mysql:mysql /usr/local/mysql/data

这时候我们应该起数据库服务。

5.1启动数据库服务

[root@localhost testdb]#cd /usr/local/mysql

[root@localhost testdb]#bin/mysqld_safe --defaults-file='/etc/my.cnf' --user=root &

启动成功!可以连接客户端检验数据

6.1连客服端

[root@localhost testdb]# mysql -u root -h localhost -P3306 -p

MySQL>

mysql> show tables; +--------------------------+ | Tables_in_testdb | +--------------------------+ | add_data1 | | add_data2 | | student_t | | xtrabackup_increment_1_t | | xtrabackup_increment_2_t | | xtrabackup_increment_3_t |

| xtrabackup_increment_4_t|

完成恢复!

四个增备份表和全备份的数据都恢复完成!

到目前为止已经把备份数据恢复完成了。但是还没有当天数据库产生的最新数据,要恢复当天的数据,要使用binlog恢复。

7.1恢复当天最新的数据,要利用binlog日志恢复。可以参照binlog的完整恢复

--获取最后一次增量的log position [root@localhost xtrabackup_increment]# cat /opt/xtrabackup_increment/2017-07-29_14-36-51/xtrabackup_binlog_info mysql_bin.000417 154 [root@localhost xtrabackup_increment]# cd /usr/local/mysql

–使用start-position 和stop-datetime 将日志追加到最新
/usr/local/mysql/bin/mysqlbinlog /usr/local/mysql/data_bak/mysql_bin.000417 /usr/local/mysql/data_bak/mysql_bin.000418 --start-position=154 | mysql -uroot -p -P3306 --socket=/usr/local/mysql/mysql.sock

到目前为止,数据更新到最后一次flush logs的数据。如果还没有达到要求。可以先flush logs ,然后把最新的binlog文件恢复。

你可能感兴趣的:(mysql,mysql)