由于最近的老生常谈的问题,zabbix数据库里面的数据量开始越来越大了,常规的mysqldump工具备份数据库的时候将导致zabbix服务异常,产生大量报警。于是,就有了之前那篇文章关于zabbix数据库的备份以及表分区。
因为我的zabbix是使用的innodb存储引擎,而percona公司开发的xtradbbackup数据库备份软件对于innodb数据库备份比mysqldump效率高很多,而且可以实现增量备份,不锁表备份。所以很适合我的需求,今天闲来无事就来研究一下xtradbbackup这款数据库备份工具。
首先,需要在percona官网下载xtradbbackup,链接在这:https://www.percona.com/downloads/XtraBackup/LATEST/
可以下载源码包安装,也可以下载rpm包安装,我这里下载的是centos 7的rpm包安装的,包名是:percona-xtrabackup-2.2.12-1.el7.x86_64.rpm
在安装rpm包之前需要安装
yum -y install perl-DBD-MySQL
之后安装的时候发现还有两个报错,需要安装两个包:
yum -y install libaio yum -y install perl-Digest-MD5
然后再安装xtradbbackup:
rpm -ivh percona-xtrabackup-2.2.12-1.el7.x86_64.rpm
安装好后可以使用innobackupex --help查看命令参数。
语法:innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
/path/to/BACKUP-DIR/文件为xtrabackup的备份文件,在备份的同时,innobackupex还会在备份目录中创建如下文件:
xtrabackup_checkpoints ―― 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息; 每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
xtrabackup_binlog_info ―― mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
xtrabackup_binlog_pos_innodb ―― 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。
xtrabackup_binary ―― 备份中用到的xtrabackup的可执行文件;
backup-my.cnf ―― 备份命令用到的配置选项信息;
说明:在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。
常用选项:
--defaults-file #数据库的配置文件路径,感觉本地备份不写也可以,远程没测试过。
--apply-log #准备在一个备份上启动mysql服务。
--copy-back #从备份目录拷贝数据,索引,日志到my.cnf文件里规定的初始位置。
--no-timestamp #创建备份时不自动生成时间目录,可以自定义备份目录名例如: /backups/mysql/base
--databases #用于指定要备份的数据库, 多个库文件使用方法: “database1 database2″
--incremental #在全备份的基础上进行增量备份,后跟增量备份存贮目录路径
--incremental-basedir=DIRECTORY #增量备份所需要的全备份路径目录或上次做增量备份的目录路径
--incremental-dir=DIRECTORY #增量备份存贮的目录路径
--redo-only #用于准备增量备份内容把数据合并到全备份目录,配合�Cincremental-dir 增量备份目录使用。
--force-non-empty-directories #如果是特定库备份还原,不需要删掉整个mysql目录,只是特定库的及相关文件就可以,还原时加上此参数就不会报错。
好了,接下来就需要测试使用xtradbbackup对数据库进行全备以及恢复的过程了。
首先创建备份目录:
mkdir -p /opt/backup
注意在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。
innobackupex --user=root --password=xxxxxx /opt/backup (PS:该情况将会自动在/opt/backup下面创建一个以时间命名的全备目录) innobackupex --user=root --password=xxxxxx --no-timestamp /opt/backup1(PS:这样将会在/opt/backup1目录下生成全备的文件及目录)
下面是备份出来的目录文件:
ls 2015-10-12_16-09-18/ backup-my.cnf CrazyEyes ibdata1 mysql performance_schema test xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile zabbix
备份的文件说明:
(1)xtrabackup_checkpoints ―― 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
cat xtrabackup_checkpoints backup_type = full-backuped #注明这是全备 from_lsn = 0 #全备的lsn起始号 to_lsn = 2026561686 #全备记录到的最大序列号 last_lsn = 2026562643 #全备完成后当前的日志序列号 compact = 0 #注明没有进行打包
(2)xtrabackup_binlog_info ―― mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
cat xtrabackup_binlog_info mysql-bin.0000011371180-1-175
(3)backup-my.cnf ―― 备份命令用到的配置选项信息和备份无关的不会记录,备份配置文件的话需要单独备份。
cat backup-my.cnf # This MySQL options file was generated by innobackupex. # The MySQL server [mysqld] innodb_checksum_algorithm=innodb innodb_log_checksum_algorithm=innodb innodb_data_file_path=ibdata1:12M:autoextend innodb_log_files_in_group=2 innodb_log_file_size=50331648 innodb_page_size=16384 innodb_log_block_size=512 innodb_undo_directory=. innodb_undo_tablespaces=0
(4)xtrabackup_info ―― 记录了mariadb的版本信息和一些属性信息,还原是检测版本匹配度时用到。
cat xtrabackup_info uuid = a2443721-70b8-11e5-ae53-000c29bc81b7 name = tool_name = innobackupex tool_command = --user=root --password=... /backup/ tool_version = 1.5.1-xtrabackup ibbackup_version = xtrabackup version 2.2.12 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 8726828) server_version = 10.0.17-MariaDB-log start_time = 2015-10-12 16:09:18 end_time = 2015-10-12 16:10:00 lock_time = 3 binlog_pos = filename 'mysql-bin.000001', position 137118, GTID of the last change '0-1-175' innodb_from_lsn = 0 innodb_to_lsn = 2026561686 partial = N incremental = N format = file compact = N compressed = N
创建好备份文件后这时数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处于不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。
需要使用innobakupex命令的--apply-log选项来使数据文件同步。
innobackupex --apply-log 2015-10-12_16-09-18 同步后的目录结构: ls 2015-10-12_16-09-18 backup-my.cnf ibdata1 ib_logfile1 performance_schema xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_logfile CrazyEyes ib_logfile0 mysql test xtrabackup_binlog_pos_innodb xtrabackup_info zabbix
在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。
命令如下:
innobackupex --user=root --password=xxxxx --no-timestamp --use-memory=500MB /backup2
设定准备数据时使用的内存限定为500M,并且不创建以时间命名的文件夹。
模拟数据库损坏以及恢复数据:
首先,删除mysql数据库的data目录下的所有数据:
rm -fr /data/mysql/* ll /data/mysql/
总用量 0
这时候无法直接关闭数据库:
service mysqld stop ERROR! MySQL server PID file could not be found!
可以使用pkill杀死数据库主进程:
pkill mysql ps aux|grep mysql root 27381 0.0 0.0 112656 976 pts/1 R+ 18:10 0:00 grep --color=auto mysql
然后检查数据库配置文件中是否在[mysqld]设置了datadir路径(PS:如果这里没有设置路径的话在恢复数据的时候将会报错,我这里设置的路径为:datadir=/data/mysql)
my.cnf文件所在路径为/etc/my.cnf
现在需要进行数据恢复:
(PS:在还原数据之前,首先需要检查datadir路径中是否含有文件,假如含有文件,恢复时将会报错)
innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。
语法:
innobackupex --copy-back /path/to/BACKUP-DIR
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。
innobackupex --copy-back /backup2/
就可以恢复数据了。之后修改数据库datadir路径的文件属主和属组:
chown -R mysql.mysql /data/mysql/
这时候可以正常的启动数据库了。
service mysqld start Starting MySQL. SUCCESS!
这个时候启动起来是重新记录二进制日志的。这样,一次全备以及数据库全备恢复的过程就结束了。
数据库增量备份以及对增量备份数据恢复:
提示:在恢复完成之后应该再次做一次完全备份,后期的增量备份都依照这次的完全备份来做。
innobackupex --user=root --password=xxxxxx --use-memory=500MB /backup3 innobackupex --apply-log /backup3/2015-10-13_08-48-25/ ls /backup3 2015-10-13_08-48-25
之后就可以使用innobackupex进行增量备份
每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。
要实现第一次增量备份,可以使用下面的命令进行:
innobackupex --user=root --password=xxxxxx --incremental /backup/ --incremental-basedir=BASEDIR
其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup/目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。
需要注意的是,增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。
命令如下:
第一次增量备份:innobackupex --user=root --password=xxxxxx --incremental /backup3/ --incremental-basedir=/backup3/2015-10-13_08-48-25/ 第二次增量备份:innobackupex --user=root --password=xxxxxx --incremental /backup3/ --incremental-basedir=/backup3/2015-10-13_08-52-12/
“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:
(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。
(2)基于所有的备份将未提交的事务进行“回滚”。
于是,操作就变成了:
innobackupex --apply-log --redo-onlyBASE-DIR innobackupex --apply-log --redo-only /backup3/2015-10-13_08-48-25/ 接着执行: innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1 innobackupex --apply-log --redo-only /backup3/2015-10-13_08-48-25/ --incremental-dir=/backup3/2015-10-13_08-52-12/ 而后是第二个增量: innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2 innobackupex --apply-log --redo-only /backup3/2015-10-13_08-48-25/ --incremental-dir=/backup3/2015-10-13_08-52-59/
其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作;
cat /backup3/2015-10-13_08-48-25/xtrabackup_checkpoints backup_type = log-applied from_lsn = 0 to_lsn = 2063010964 last_lsn = 2063010964 compact = 0 cat /backup3/2015-10-13_08-52-59/xtrabackup_checkpoints backup_type = incremental from_lsn = 2062984015 to_lsn = 2063010964 last_lsn = 2063010964 compact = 0
可以看到目前所有的增量备份都还原到了全备上面,这时候就可以进行数据恢复了。
rm -fr /data/mysql/* pkill mysql ps aux|grep mysql root 15699 0.0 0.0 112656 980 pts/1 R+ 09:29 0:00 grep --color=auto mysql rm -fr /data/mysql/* innobackupex --copy-back /backup3/2015-10-13_08-48-25/ chown -R mysql.mysql /data/mysql/ service mysqld start Starting MySQL...... SUCCESS!
好了,模拟数据丢失以及增量备份恢复做完了,假如在数据损毁不像我这样直接rm -fr这么干净的话可以在最近的一次增量备份合并到全备上面并恢复数据库之后将最近的一个binlog日志导入并恢复数据。
cat /backup3/2015-10-13_08-48-25/xtrabackup_binlog_info mysql-bin.000001133183220-1-31629 mysqlbinlog --start-position=13318322 /data/mysql/mysql-bin.000001 > /tmp/statements.sql
这样就可以恢复到出故障前的数据库状态了。(PS这个操作要在启动数据库之前进行操作)