MySQL数据安全系列之二:数据备份

从上文 《MySQL数据安全系列之一:现实案例》中,我们看到了MySQL数据库一旦发生外部异常,对数据库的数据安全可能是致命的,上述这个数据库,如果损坏的不止是全局表空间,同时其他表空间也被破坏了,或者干脆没有设置innodb_file_per_table=1,那么,数据的永久丢失是不可避免的,几年的游戏数据损失,其后果真的不堪设想。那么我们应该怎么做才能避免类似上文中出现的问题?
其实对于数据库来说,避免数据大面积丢失的方法还是有很多的,其中最常用的就是对重要数据进行定期备份,而对于MySQL来说,官方的和非官方的备份工具有很多,接下去就让我们来一一认识一下。


  • mysqldump
    mysqldump是MySQL官方提供的数据备份工具,其主要作用就是把数据库中的数据转化成一条条的insert语句保存到.sql脚本中。
    mysqldump的优势:支持所有MySQL支持的存储引擎的数据库数据导出
    mysqldump的劣势:数据导出时需要锁表,导致在备份的时间段内,数据库的服务是中断的;
    mysqldump导出是单线程的,如果库比较大,这个导出的时间周期会很长,导致数据库停服的周期变长。
    所以mysqldump一般在较小的库上使用,大库只有在允许停服的情况下才能使用。


mysqldump流程


  • mydumper/myloader
 mydumper/myloader是Percona公司开发的一套用于MySQL数据库InnoDB数据表导出的工具,其主要原理是利用了MySQL的MVCC机制(隔离级别Read Repeatable)原理,在RR级别下,一个事务在运行阶段看到的数据永远是相同的(注:MySQL数据库的隔离级别设置请查看相关手册),在开始阶段给所有表都上读锁(根据参数不同上read lock或者整个上flush table with read lock,两者的区别在于前者不需要关闭表,后者需要关闭表),然后获取当前执行的binlog位置,这样做的主要目的是让恢复后的数据在跟上主做复制的时候,能够指定正确的起始位置,获取了binlog执行位置后,在释放锁之前,需要把所有dump数据的事务启动(start transaction),这样就保证了当前开始dump的数据和获取的binlog的位置是一致的。事务启动后就可以释放掉锁了,从上锁到释放锁这段过程,其实是比较短的,所以mydumper并不像mysqldump一样需要锁定整个dump过程,只需要锁定获取binlog到启动事务一段时间即可,基本上不影响线上业务。myloader是数据导入工具,允许数据多线程导入。
mydumper的优势:支持多线程导出/导入,基本不影响线上应用
mydumper的劣势:只支持InnoDB表的导出导入
mydumper流程

  • xtrabackup/innobackupex
 不得不说Percona是MySQL领域一家伟大的公司,除了mydumper/myloader,Percona还提供了另外一个闻名于MySQL界的备份工具——xtrabackup/innobackupex,xtrabackup只支持InnoDB/xtraDB存储引擎,不同于mydumper/myloader的逻辑备份(把数据导成sql语句),xtrabackup实现了物理上的备份,就是直接拷贝数据和redo log,利用MySQL自身的recover机制来恢复数据(innobackupex是xtrabackup的一个变种,支持非InnoDB表的备份,对于非InnoDB表需要锁表)。
   xtrabackup在备份的时候会监控redo log文件,这一特性使其具备上述两种备份工具不具有的另外一种能力能力——增量备份,MySQL使用WLA(write log ahead日志先行)策略,所有对数据上的修改必定会先写入redo log,所以实现对redo log的增量备份就可以实现对整个数据的增量备份。

  • point-in-time
上述三种备份各有所长,但是它们有一个共同的问题,没法实现把数据恢复到指定的时间点,因为无论是mysqldump/mydumper备份,还是xtrabackup备份,都是在某个时间点进行的,所以在该时间点之前的某个点时的数据,无法通过备份进行恢复,它们只能恢复到备份的点,无法恢复到备份前任意一个时间点。那么对于这种需要恢复到某个时间点(point-in-time)的需求,MySQL要如何实现?
要实现point-in-time恢复,MySQL需要通过定时备份和增量备份binlog相配合的方式进行,MySQL binlog是MySQL层的日志,可以是逻辑日志(statement),也可以是物理日志(row),区别于InnoDB层的日志redo log,binlog支持所有MySQL的引擎。MySQL binlog会记录数据改变,每行(row格式)数据改变都会配有一个时间戳,这就为我们的point-in-time恢复提供了有利的条件。
前面已经提到过,point-in-time恢复需要配合全量备份使用,备份工具(mysqldump、mydumper。xtrabackup)在备份完成后都会在日志中提供一个当前对应执行的binlog的位置,通过这个位置可以找到当前备份执行到的binlog时间点,以后通过备份该时间点以后的binlog数据,就可以在恢复的时候恢复到该备份后任意一个时间点的位置(为了恢复时间不要过长,可以定期做全量备份,然后在该基础上增量)。

  • 总结
以上介绍了在MySQL数据库下各种备份的实现,用户可以根据不同的需求进行不同的选择,定时做好备份是防止数据丢失的一个有力措施,需要引起MySQL乃至数据库使用者的足够重视。
------------------------------------------------------------------------------------------------------------------------------
通过定时备份,能避免大面积的数据丢失,但如果服务出现异常宕机,通过备份来恢复数据,停止对外服务的风险是不能避免的,因为数据恢复根据数据量的大小不同,通常都需要很长的恢复时间,而这段时间内服务对外都是不可用的,如果对服务要求比较高,还是需要使用MySQL的高可用方案。

本文来自网易实践者社区,经作者蒋鸿翔授权发布。