小型网站MYSQL问题二:Percona Xtrabackup实现数据库备份和恢复

故事背景:前面大胆的选择了innodb,接下来就要考虑数据库的备份和恢复。俗话说“常在河边走,哪能不湿鞋“,自从接触数据这块,使我一直对它保持敬畏之心。在这里使用了percona公司的xtrabckup工具来实现数据库备份和恢复。操作步骤记录如下:

1、安装软件仓库(不要问我为什么不用源码安装,好吧,其实我懒。)

wget https://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm
rpm -ivh percona-release-0.1-3.noarch.rpm
rpm -ql percona-release
    /etc/pki/rpm-gpg/RPM-GPG-KEY-Percona
    /etc/yum.repos.d/percona-release.repo
    /usr/share/doc/percona-release-0.1
    /usr/share/doc/percona-release-0.1/RPM-GPG-KEY-Percona
yum -y install percona-xtrabackup

2、备份策略及准备测试数据

采用先全备份加增量备份的方案。在利用xtrabackup对innodb表做备份工作时,建议mysql启用“innodb_file_per_table=1”变量且同时启用innodb_file_per_table = 1 innodb_expand_import = 1

这样使每表都有一个自己的表空间,不然很难进行单表备份和还原。还有二进制日志文件就不要与数据文件放在同一个目录了,你不想当数据丢失时,二进制日志也一同丢了。

测试数据:

mysql> SELECT VERSION(); 
    +------------+ 
    | VERSION()  | 
    +------------+ 
    | 5.5.36-log | 
    +------------+ 
    1 row in set (0.00 sec) 
mysql> SHOW DATABASES; #创建了一个mydb1数据库 
    +--------------------+ 
    | Database          | 
    +--------------------+ 
    | information_schema | 
    | mydb1              | 
    | mysql              | 
    | performance_schema | 
    | test              | 
    +--------------------+ 
mysql> SELECT * FROM mydb1.tb1; #表中只有一条数据 
    +----+------+------+ 
    | id | name | age  | 
    +----+------+------+ 
    |  1 | tom  |  10 | 
    +----+------+------+

创建备份数据存放目录:

mkdir -pv /backup/{fullbackup,incremental} 
    #fullbackup  存放全备份数据 
    #incremental 存放增量备份数据

创建复制用户:

mysql> GRANT RELOAD,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'bkuser'@'localhost' IDENTIFIED BY '123456'; 
mysql> FLUSH PRIVILEGES;

3、全备份数据

innobackupex --user=bkuser --password=123456 /backup/fullbackup/ 
    #最后出现“150415 16:30:23  innobackupex: completed OK!”这样的信息表示备份完成 
ls /backup/fullbackup/2015-04-15_16-30-19/ 
    backup-my.cnf  mysql              xtrabackup_binary      xtrabackup_logfile 
    ibdata1        performance_schema  xtrabackup_binlog_info 
    mydb1          test                xtrabackup_checkpoints 
cat /backup/fullbackup/2015-04-15_16-30-19/xtrabackup_checkpoints 
    backup_type = full-backuped 
    from_lsn = 0 
    to_lsn = 1644877 
    last_lsn = 1644877 
    compact = 0

4、增量备份数据

先做一些数据修改:

mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('jack',20); 
mysql> SELECT * FROM tb1;  #增加一条数据 
    +----+------+------+ 
    | id | name | age  | 
    +----+------+------+ 
    |  1 | tom  |  10 | 
    |  2 | jack |  20 | 
    +----+------+------+

做第一次增量备份:

innobackupex --user=bkuser --password=123456 --incremental /backup/incremental/ --incremental-basedir=/backup/fullbackup/2015-04-15_16-30-19/ 
ls /backup/incremental/2015-04-15_16-42-00/ 
    backup-my.cnf  mydb1              test                    xtrabackup_checkpoints 
    ibdata1.delta  mysql              xtrabackup_binary      xtrabackup_logfile 
    ibdata1.meta  performance_schema  xtrabackup_binlog_info 
cat /backup/incremental/2015-04-15_16-42-00/xtrabackup_checkpoints 
    backup_type = incremental 
    from_lsn = 1644877  #这是全备时的"to_lsn"值 
    to_lsn = 1645178 
    last_lsn = 1645178 
    compact = 0

再做数据修改:

mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('jason',30); 
mysql> SELECT * FROM tb1; 
    +----+-------+------+ 
    | id | name  | age  | 
    +----+-------+------+ 
    |  1 | tom  |  10 | 
    |  2 | jack  |  20 | 
    |  3 | jason |  30 | 
    +----+-------+------+

做第二次增量备份:

innobackupex --user=bkuser --password=123456 --incremental /backup/incremental/ --incremental-basedir=/backup/incremental/2015-04-15_16-42-00/ 
    #这里的"--incremental-basedir"是指向第一次增量备份的目录 
ls /backup/incremental/2015-04-15_16-49-07/ 
    backup-my.cnf  mydb1              test                    xtrabackup_checkpoints 
    ibdata1.delta  mysql              xtrabackup_binary      xtrabackup_logfile 
    ibdata1.meta  performance_schema  xtrabackup_binlog_info 
cat /backup/incremental/2015-04-15_16-49-07/xtrabackup_checkpoints 
    backup_type = incremental 
    from_lsn = 1645178 #这是第一次增量的"to_lsn"值 
    to_lsn = 1645463 
    last_lsn = 1645463 
    compact = 0

再来做一次数据修改,以便演示根据二进制日志做时间点的恢复:

mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('lucky',40); 
mysql> SELECT * FROM tb1; 
    +----+-------+------+ 
    | id | name  | age  | 
    +----+-------+------+ 
    |  1 | tom  |  10 | 
    |  2 | jack  |  20 | 
    |  3 | jason |  30 | 
    |  4 | lucky |  40 | 
    +----+-------+------+

5、恢复

5.1、数据破坏

service mysqld stop 
rm -rf /mnt/mydata/data/*  #把数据目录数据全部删除

对于xtrabackup做数据恢复的理解:

xtrabackup做数据恢复与mysqldump这样的逻辑备份工作的恢复有很大的区别,xtrabackup进行数据恢复时需要把各个增量的数据备份与全备份的数据进行合并,

对每次增量备份的合并只能将已提交的事务进行重放(redo),对合备份的数据恢复也只能做redo操作,把各个增量都合并完成后再把没有提交的事务进行回滚(undo)操作,

合并完增量备份后,全备份的“xtrabackup_checkpoints”文件中的“last_lsn”应该是最后一次增量备份时的值,这些合并做redo的过程就是恢复数据前的准备工作(prepare)。

而真正在做数据恢复,建议先把全备和增量备份的文件都copy一份为副本,避免操作失误导致备份文件的损坏。

5.2、数据恢复的准备(prepare)工作

#准备全备份的数据 
innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ 
#准备第一次增量数据 
innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ --incremental-dir=/backup/incremental/2015-04-15_16-42-00/ 
#准备第二次增量数据 
innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ --incremental-dir=/backup/incremental/2015-04-15_16-49-07/
cat /backup/fullbackup/2015-04-15_16-30-19/xtrabackup_checkpoints 
    backup_type = full-prepared 
    from_lsn = 0 
    to_lsn = 1645463 #这是最后一次增量备份的位置,到此数据已全部合并 
    last_lsn = 1645463 
    compact = 0

5.3、真正数据恢复

innobackupex --copy-back /backup/fullbackup/2015-04-15_16-30-19/  #仅一个“--copy-back”选项 
ls /mnt/mydata/data/ 
    ibdata1  mydb1  mysql  performance_schema  test
chown -R mysql.mysql /mnt/mydata/data/  #修改恢复数据的属主与属组 
service mysqld start 
    Starting MySQL.. SUCCESS! 
mysql> SELECT * FROM mydb1.tb1;  #检查数据 
    +----+-------+------+ 
    | id | name  | age  | 
    +----+-------+------+ 
    |  1 | tom  |  10 | 
    |  2 | jack  |  20 | 
    |  3 | jason |  30 | 
    +----+-------+------+ 
#lucky信息还没有恢复

5.4、利用二进制日志文件基于时间点恢复

查看最后一次增量备份时的二进制日志文件及position信息:
cat /backup/incremental/2015-04-15_16-49-07/xtrabackup_binlog_info 
    mysql-bin.000031    1665  
mysqlbinlog --start-position=1665 /var/log/mysql_log/mysql-bin.000031 > /tmp/position.sql 
    #用mysqlbinlog工具导出最后一次增量备份后的sql操作
导入数据:
mysql> source /tmp/position.sql 
mysql> SELECT * FROM mydb1.tb1; 
    +----+-------+------+ 
    | id | name  | age  | 
    +----+-------+------+ 
    |  1 | tom  |  10 | 
    |  2 | jack  |  20 | 
    |  3 | jason |  30 | 
    |  4 | lucky |  40 | 
    +----+-------+------+ 
#数据全部恢复

6、总结

利用innobackupex工具可对在有混合存储引擎的场景下对数据库进行全备份,当是备份innodb表时innobackupex脚本内部会自动调用xtrabackup工具来进行备份操作,

在数据还原时应停止mysql实例,清空数据目录,然后先做prepare准备工作,第二步才是真正的数据还原(–copy-back),数据还原到数据目录后不要忘记修改数据目录的权限。

当然innobackupex工具也能实现对单库单表的导出、导出,如果是对Innodb表,那建议直接用xtrabackup工具,这样更直观的使用各个选项进行备份。

============================华丽分隔线(下面是重点)================================================

背景:在到第5.3步的时候,数据库启动失败。why、what、fuck。说好的一条龙服务?

痛定思痛,上日志。

151216 11:16:20
mysqld_safe Starting mysqld daemon with databases from /data/mysql
151216 11:16:20 [Note] /usr/libexec/mysqld (mysqld 5.5.47-log) starting as process 2931 ...
151216 11:16:20 [Note] Plugin 'FEDERATED' is disabled.
151216 11:16:20 InnoDB: The InnoDB memory heap is disabled
151216 11:16:20 InnoDB: Mutexes and rw_locks use GCC atomic builtins
151216 11:16:20 InnoDB: Compressed tables use zlib 1.2.3
151216 11:16:20 InnoDB: Using Linux native AIO
151216 11:16:20 InnoDB: Initializing buffer pool, size = 128.0M
151216 11:16:20 InnoDB: Completed initialization of buffer pool
InnoDB: Error: log file ./ib_logfile0 is of different size 0 50331648 bytes        #这里是48M
InnoDB: than specified in the .cnf file 0 5242880 bytes!           #这里是5M
151216 11:16:20 [ERROR] Plugin 'InnoDB' init function returned error.
151216 11:16:20 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.   #注册引擎失败,打击好大
151216 11:16:20 [ERROR] Unknown/unsupported storage engine: innodb     #什么,又不支持innodb
151216 11:16:20 [ERROR] Aborting
 
151216 11:16:20 [Note] /usr/libexec/mysqld: Shutdown complete
 
151216 11:16:20 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

首先我删除了恢复到/data/mysql目录下面的ibdata1和ib_logfile0、ib_logfile1,此时可以启动数据库,然而提示表不存在。

向各位老师请教后,修改innodb_log_file_size=48M并写入/etc/my.cnf,启动正常。

总结:innodb_log_file_size参数属于mysql系统参数,当配置不当时,mysql会启动失败。使用xtrabackup备份时默认值是5M,但是当迁移到新的环境后,初始化为48M,导致不匹配。后续应该将此参数写入/etc/my.cnf防止迁移带来的参数不匹配问题。

Command-Line Format --innodb_log_file_size=#
System Variable Name innodb_log_file_size
Variable Scope Global
Dynamic Variable No
Permitted Values Type integer
Default 5242880
Min Value 1048576
Max Value 4GB / innodb_log_files_in_group

The size in bytes of each log file in a log group. The combined size of log files (innodb_log_file_size * innodb_log_files_in_group) cannot exceed a maximum value that is slightly less than 4GB. A pair of 2047 MB log files, for example, would allow you to approach the range limit but not exceed it. The default value is 5MB. Sensible values range from 1MB to 1/N-th of the size of the buffer pool, where N is the number of log files in the group. The larger the value, the less checkpoint flush activity is needed in the buffer pool, saving disk I/O. Larger log files also make crash recovery slower, although improvements to recovery performance in MySQL 5.5 and higher make the log file size less of a consideration. For general I/O tuning advice, 

具体参考:http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_log_file_size

原创文章,作者:陈近南,如若转载,请注明出处:http://www.178linux.com/10139

赞 (1)
陈近南陈近南
上一篇 2015-12-19 20:09
下一篇 2015-12-19 20:30

相关推荐

  • Recycled和Recycler的故事

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://jeffyyko.blog.51cto.com/28563/156012      首先说明一下,这里不是英语课堂,本文也不是来辨析Recycled和Recycler这两个单词的含义。Recy…

    Linux干货 2015-03-25
  • sed 高级用法(1) 之 n N

    前言 我在参考其它多个Blog中发现,有些Blog中sed的功能介绍和实际有出入,这可能和版本有关系,正如sed文档中所说“might change in future versions”,所以本文sed是以4.2.1为例。如果以后sed更新版本了,有可能会不一样。 好记性不如烂笔头! sed的工作原理 sed维护着两个数据的缓冲空间,一个是模式空间(pat…

    Linux干货 2015-07-03
  • Memcached + MSM 实现Tomcat Session保持

    Memcached + MSM 实现Tomcat Session保持 tomcat memcached 前言 Memcached介绍 MSM介绍 实验拓扑 实验环境 实验步骤 安装配置Tomcat 安装配置Nginx负载均衡 安装配置Memcached + MSM 总结 前言 上篇文章我们实现了session sticky和session clus…

    2016-04-22
  • 搭建discuz服务器

      Discuz是目前比较流行的社区论坛系统,其具有安装简便、功能强大的特点,下面以LAMP为基础平台来搭建discuz服务器。   一、安装apache服务   二、安装php   三、安装mysql   四、安装php-mysql   五、启动mysql服务   六、创建数据库 &nb…

    Linux干货 2016-03-18
  • 20本最好的Linux免费书籍

    前些天Neo推荐了一个网站有《超过100本的linux免费书籍》,这里,我也向大家推荐20本最好的Linux免费书籍,当然,也是英文版的。 1. Ubuntu Pocket Guide and Reference 一本介绍关于Ubuntu 8.04和8.10的使用书。 Website www.ubuntupocketguide.com Author Keir…

    Linux干货 2015-04-01
  • Btrfs文件系统的管理和应用

        Btrfs(我们称之为Butter FS或者B-tree FS)被称为新一代的linux文件系统。一直以来,EXT文件系统以其卓越的稳定性成为linux标准的文件系统。但近年来,EXT3暴露出一些扩展性的问题(如单一文件大小限制、总文件系统大小限制等),于是便催生了EXT4。但同时,Btrfs向人们展现出诸多优…

    Linux干货 2016-02-14

评论列表(3条)

  • stanley
    stanley 2015-12-19 20:22

    非常不错,久违的好博客,已置顶

  • 以马内利
    以马内利 2015-12-21 08:54

    我也发现innodb_log_file_size的问题了,哈哈。 这个坑貌似配过的都得踩一脚

  • bigwinner
    bigwinner 2016-04-14 11:05

    楼主写的十分详细,线上如果出问题,不会有时间一步一步的这么去恢复的,都是通过脚本实现的;