下面我们就看一下常见的备份工具,以及目前最流行的PerconaXtraBackup的备份流程。一、备份工具介绍1。1常见备份工具介绍 MySQL常见的备份工具主要分为三种:逻辑备份,包含mysqldump和Mydumper;物理备份,包含Mysqlbackup和PerconaXtraBackup;binlog备份,包含mysqlbinlog。 这里先说一下binlog备份,它只是把binlog又复制了一份,并且需要在逻辑备份或者物理备份的基础上才能进行数据恢复,无法单独进行数据恢复。(1)逻辑备份:mysqldump mysqldump备份出的文件就是sql文件,其核心就是对每个表执行select,然后转化成相应的insert语句。mysqldump的备份流程大致如下:对某个库下所有表加读锁;循环备份备份表数据;释放读锁;循环上面三个步骤;备份完毕。 从上面可以看出在mysqldump备份期间,备份到某个数据库时,该数据库下的表都会处于只读状态,无法对表进行任何变更,直到该库下的表备份完毕,这对于线上环境一般是无法接受的。若是指定了masterdata或者dumpslave则会在备份开始时加全局读锁(FLUSHTABLESWITHREADLOCK),直到备份结束。当然我们可以选一个从库进行备份,这样就不会影响线上业务。另外使用mysqldump备份还有一个最大的好处,因为备份出来的是sql语句,所以它支持跨平台和跨版本的数据迁移或者恢复,这是物理备份无法做到的。 但是也正是因为mysqldump备份出来的是sql语句,在使用时要更加注意,否则可能会酿成大祸。例如,使用mysqldump常见的问题有:本来迁移部分数据到新实例,结果把原有数据删除了;由于时区问题,发现恢复出来的表和时间相关的数据不对;在主库导入备份数据后,发现从库没有同步;由于字符集问题,发现恢复后数据出现了乱码;。。。 所以使用mysqldump时一定要了解各个选项的作用,以及确认备份出来的sql文件里会有什么操作,会对现有数据造成什么影响。 Mydumper原理与Mysqldump原理类似,最大的区别是引入了多线程备份,每个备份线程备份一部分表,当然并发粒度可以到行级,达到多线程备份的目的。这里不再单独介绍。(2)物理备份:PerconaXtraBackup PerconaXtraBackup是Percona公司开发的一个用于MySQL数据库物理热备的备份工具,是基于InnoDB的崩溃恢复功能来实现的。它的基本工作原理如下:在启动时创建一个redolog拷贝进程,获取并记录当前的日志序列号(LSN),从该位点开始持续拷贝有变化的redolog;开启idb文件拷贝线程,拷贝ibdata1,undotablespaces及所有的ibd文件;ibd文件拷贝结束,通知调用FTWRL(或加备份锁);备份非InnoDB数据(。frm、。MRG、。MYD、。MYI。。。。。。等文件);备份slave和binlog相关信息;刷新日志,拷贝最新的redolog完成后退出日志拷贝线程;释放全局锁,记录备份元数据等,备份结束。 PerconaXtraBackup在进行恢复时会应用拷贝的redolog,应用已提交的事务,回滚未提交的事物,将数据库恢复到一致性状态。因为PerconaXtraBackup备份出来的是物理文件,所以在使用备份出的文件进行恢复或者迁移时,不会像mysqldump那样会存在很多问题。 使用XtraBackup备份时根据备份参数设置不同,对数据库的变更会造成不同程度的影响,具体影响会在下文分析。(3)备份工具对比 通过对比发现,XtraBackup具有对数据库影响小,且能快速恢复的优点,在日常备份中是首选;mysqldump使用相对更加灵活,但是使用是要注意对数据库原有数据的影响。1。2备份策略 备份策略主要有:全量备份和增量备份,再加上binlog备份。 目前去哪儿网数据库备份主要采用XtraBackup全量备份binlog备份。数据库的重要级别不同,全量备份的频率不同。备份程序主要架构如下: 说明:备份调度程序会根据设置的备份策略来调度备份任务;数据库备份采用XtraBackup流式备份,直接传输到备份机;备份完成后applylog,这样既可以验证备份的可用性,也在使用备份时减少了applylog时间;压缩备份;binlog备份是定时执行,使用rsync存储到MFS存储。二、XtraBackup备份流程解析 PerconaXtraBackup是目前备份MySQL使用最广泛的工具。在备份过程中,数据库可以进行正常的读写或者其他变更操作,但是偶尔也会遇见备份引起的元数据锁,或提交事务时发现被binloglock阻塞等情况。下面我们就看一下PerconaXtraBackup的备份流程和加锁时机。 说明:以下对PerconaXtraBackup的分析都是基于2。4。23的版本,其他版本会略有差别,但是关键步骤基本相同。2。1拷贝redo日志 XtraBackup在备份开始时,会创建一个后台线程,专门用于拷贝数据库的redolog。首先XtraBackup会扫描每组redolog的头部,找出当前的checkpointlsn,然后从该lsn后顺序拷贝所有的redolog,包括后续新产生的redolog。该线程会一直持续到将非事务表完全拷贝完成,才会安全退出。备份日志输出中会记录拷贝开始时的checkpointlsn。日志输出如下: 2。2拷贝ibd文件 在拷贝ibd文件之前,会先扫描数据库的数据文件目录,获取ibdata1,undotablespaces及所有的ibd文件列表,并会记录相应的spaceid,因为在恢复时需要这些spaceid来找到对应doublewritebuffer里页面的内容,以及对应的redolog条目。然后开始循环拷贝ibdata1,undotablespaces及所有的ibd文件。 这里可通过设置parallel进行多线程备份,提高物理文件的拷贝效率。不设置则默认为1。2。3拷贝非ibd文件 在所有ibd文件拷贝完成后,XtraBackup开始备份非ibd文件。这一部分的逻辑比较复杂,因为备份非ibd文件前需要加锁,具体是否会加锁主要受到nolock参数设置的影响。2。3。1nolock选项参数说明 若是设置了nolock为TRUE,则不会使用FLUSHTABLESWITHREADLOCK去加全局读锁,但是若备份过程中对nonInnoDB表执行了DDL或者DML操作,这会导致备份的不一致,恢复出来的数据就会有问题。所以是不建议将nolock为TRUE,默认值是FALSE,也就是在不指定该选项的情况下会在备份非ibd文件前加全局读锁。 下面我们结合源码来看看判断是否加全局锁这部分的具体流程逻辑: 流程图如下: 总结来看: 1)若nolock为FALSE(默认值),则先施加全局读锁,然后再进行拷贝文件,另外若safeslavebackup设置为TRUE,则会在加全局锁之前关闭SQLTHREAD线程; 2)若nolock为TRUE,则不会施加锁,直接进行拷贝文件。2。3。2加锁处理逻辑 加锁的逻辑主要由locktablesmaybe实现,先看一下locktablesmaybe源代码,如下: locktablesmaybe函数简化处理流程如下: 1)若备份实例上已经加锁(LOCKTABLESFORBACKUPFLUSHTABLESWITHREADLOCK)或者设置lockddlpertable则直接返回; 2)若支持备份锁,则执行LOCKTABLESFORBACKUP; 3)若不支持备份锁,则执行FLUSHTABLESWITHREADLOCK。根据相应选项设置,在执行该操作前会判断是否有执行中的DDLDML,以及等待超时时间,是否kill对应的未结束的事务等。 从上文中我们还看到一个参数safeslavebackup,该参数的主要作用是: 若是在从库执行的备份操作时设置了该参数,可以防止因从库同步主库操作,而导致XtraBackup长时间请求不到锁而造成备份失败。 若是设置了safeslavebackup为TRUE,那么会执行STOPSLAVESQLTHREAD,并等待Slaveopentemptables为零才开始拷贝非ibd文件,Slaveopentemptables为零说明SQLthread执行的事务都已经完成,这样就能保证备份的一致性。并且此时也不会有在执行的事务阻塞XtraBackup施加全局锁。2。4备份slave和binlog信息 备份完非ibd文件后,将会备份slave和binlog信息。如果命令行中指定了slaveinfo,则会执行SHOWSLAVESTATUS获取复制的相关信息并记录到xtrabackupslaveinfo文件中,主要包含从库同步到的主库的binlog位点(RelayMasterLogFile,ExecMasterLogPos)或者GTID值(ExecutedGtidSet)等。下面是基于GTID复制备份时xtrabackupslaveinfo文件记录的复制相关信息:SETGLOBALgtidpurged6b7bda9f15f011ecba14fa163ea367a4:183,9841546e15f011ec9557fa163e736db4:1;CHANGEMASTERTOMASTERAUTOPOSITION1复制代码如果命令行中指定了binloginfo,则会执行SHOWMASTERSTATUS获取Binlog的位置点信息,并记录到xtrabackupbinloginfo文件中。主要信息包含当前的binlog文件名,binlog位点以及当前的GTID。binloginfo无需显式指定,因为它的默认值为AUTO,如果开启了Binlog,则为ON。xtrabackupbinloginfo文件内容如下: mysqlbin。00000420046b7bda9f15f011ecba14fa163ea367a4:183,9841546e15f011ec9557fa163e736db4:1mysqlbin。00000420046b7bda9f15f011ecba14fa163ea367a4:183,9841546e15f011ec9557fa163e736db4:1复制代码 需要注意,在支持备份锁的实例上备份,指定了slaveinfo或binloginfo均会先施加binlog备份锁(LOCKBINLOGFORBACKUP),这会阻塞任何会更改binlog位点的操作。2。5备份结束 备份完数据库的所有文件和binlog等相关信息,备份工作就基本完成了,之后主要执行的操作如下: 1)执行FLUSHNOWRITETOBINLOGENGINELOGS,将所有的redolog刷盘; 2)停止redolog复制线程; 3)释放全局读锁(备份锁),binlog锁; 4)开启SQLTHREAD; 5)拷贝ibbufferpool和iblrudump文件; 6)生成配置文件backupmy。cnf; 7)打印备份信息到xtrabackupinfo文件,这些信息主要包含备份时使用的参数信息,备份起止时间,binlog位点信息,以及将会回到的lsn点。 下面是xtrabackupinfo记录的部分内容: 三、PerconaXtraBackup和锁相关的参数与操作3。1相关参数lockddl:若在支持备份锁的实例上指定该选项,则会在备份开始时执行LOCKTABLESFORBACKUP,以阻止所有的DDL操作。加锁时间是在拷贝redolog的线程创建前,并持续加锁到dumpbufferpool前释放锁。看一下相关的日志: lockddlpertable:在备份开始时对每个innodb表施加元数据锁,防止其上的DDL操作。加锁时间也是在拷贝redolog的线程创建前,持续到所有备份工作完成后才释放锁。看一下相关的备份日志: 加锁对应的函数是mdllocktables,释放锁对应的函数是mdlunlockall,主要是执行COMMIT,结束mdllocktables中开启的显式事务,来释放MDL锁。mdllocktables流程如下: nolock详见2。3。1节内容 上面参数lockddl和lockddlpertable是在PerconaXtraBackup2。4。8之后添加的,因为MySQL5。7新增了一个叫做SortedIndexBuilds的功能,这会导致某些DDL操作不记录重做日志而导致备份失败。使用lockddl或lockddlpertable就会在备份开始时施加锁,阻止DDL操作。 另外,若备份时指定了lockddl或lockddlpertable,则在备份非ibd文件时就不是再有加锁操作。3。2数据库中执行的加锁操作LOCKTABLESFORBACKUP:使用新的MDL类型锁,用于阻止所有非事务表的DML,以及所有类型表的DDL操作,但是不影响无锁情况的select操作和对事务表的DML操作。在LOCKTABLESFORBACKUP下执行DDL或者对非事务表执行DML,则会被堵塞,执行showprocesslist可以看到被阻塞线程状态为Waitingforbackuplock。LOCKBINLOGFORBACKUP:使用的是另一种新的MDL类型锁,用于阻止所有可能更改二进制日志位置或ExecMasterLogPos或ExecGtidSet的操作。在LOCKBINLOGFORBACKUP下执行任何会更改binlog位点的操作都会被阻塞,执行showprocesslist可以看到被阻塞线程状态为Waitingforbinloglock。FLUSHTABLESWITHREADLOCK简称(FTWRL):关闭所有打开的表并使用全局读锁锁定所有数据库的所有表,这时数据库处于只读状态,任何DDLDML操作都会被阻塞。执行showprocesslist可以看到被阻塞线程状态为Waitingforglobalreadlock。另外,由于FTWRL需要关闭表,如有大查询,会导致FTWRL等待,进而导致DMLDDL堵塞的时间变长。即使是备库,也有SQL线程在复制来源于主库的更新,上全局锁时,会导致主备库延迟。 注意:LOCKTABLESFORBACKUP和LOCKBINLOGFORBACKUP语句只有在支持备份锁的实例上才会执行,PerconaServerforMySQL已经在5。6。1664。0版本开始支持这种更加轻量的备份锁。四、思考 Q1:使用XtraBackup备份的文件进行恢复时,恢复到哪个时间点?A1:恢复到执行LOCKBINLOGFORBACKUP或FLUSHTABLESWITHREADLOCK的时间点,因为这时任何改变binlog位点的操作都会被阻塞,redolog和binlog是一致的。 Q2:在开启binlog的情况下,MySQL的奔溃恢复是同时依赖binlog和redolog这两种日志的,为什么XtraBackup不用备份binlog? A2:因为在备份中有执行LOCKBINLOGFORBACKUPFLUSHTABLESWITHREADLOCK,阻止了任何改变binlog位点的操作,这样只需要根据redolog将有commitlog的事务提交,没有commitlog的事务进行回滚即可。 Q3:使用PerconaXtraBackup备份完成后redo的位点是和binlog是一样还是比binlog多一些? A3:通过分析备份流程可以发现备份binlog位点信息(加binlog锁)是发生在停止redo拷贝线程前,而释放锁是在停止redo拷贝线之后,所以redolog会多一些。锁住了binlog保证了在该binlog位点前已经提交的事务的redolog都有commitlog的信息,未提交的事物也就没有对应的commitlog的信息,即便在锁住binlog后有Innodb表新的DML产生的redolog,但是事务无法提交,也就没有commitlog的信息的,最后在回放的过程中对没有commitlog的事务进行回滚就可以了。 Q4:PerconaXtraBackup什么时候会加锁,以及影响加锁时间长度的因素有哪些? A4:上面进行了分析,加锁操作只在备份非ibd文件时执行,加锁时长主要和非事务表的数量和大小有关,非事务表的数量越多,体积越大,拷贝文件所用的时间越长,那么加锁时间也就越长。也会和redolog生成的速度有关,只是redolog刷盘受到多个因素的影响,未及时刷盘的redolog一般很小。 Q5:PerconaXtraBackup和mysqldump选择哪个更好? A5:通过上面的的解析,若是整个实例备份,首先选择PerconaXtraBackup,因为对数据库的影响最小。若只是备份某个库表,这个就要视数据量而定,若数据量不大可以使用mysqldump。注意,对数据库做备份时最好选择业务连接最少的从库,因为备份也会消耗一定的资源,避免影响业务。