当前位置: 首页 > 科技观察

MySQL,在线热备核心原理!

时间:2023-03-13 01:38:47 科技观察

开发的童鞋< titlesplit >每次对MySQL数据库表进行重大操作前都会向DBA申请数据库备份,例如:修改表结构;批量修改或删除数据;画外音:也就是说,你是直接操作,没有备份吗?DBA童鞋如何备份MySQL?研究了几十个RD和QA,基本上有3个答案:不确定;在线逻辑备份,mysqldump;离线物理备份(冷备份),从库中拷贝文件;其实DBA是如何备份MySQL库的呢?现在基本上都是用PXB的方案。今天就给大家讲讲MySQL备份的来龙去脉和内核原理。在线逻辑备份,mysqldump怎么了?mysqldump是MySQL工具集中的一个工具,可以用来导出或者备份数据。mysqldump的输出是一组包含建表和插入数据的SQL语句,类似这样:--MySQLdump1.2.3--Host:localhostDatabase:test--Serverversion4.5.6CREATETABLEt_user(idint(11)NOTNULLunique,namevarchar(40)NOTNULLdefault'',PRIMARYKEY(id));INSERTINTOt_userVALUES(1,'shenjian');INSERTINTOt_userVALUES(2,'zhangsan');INSERTINTOt_userVALUES(3,'lisi');因此,它被称为逻辑备份。使用mysqldump备份的好处是可以在线进行,不影响数据库提供的持续在线服务。缺点也很明显:相对于物理备份复制库文件,备份和恢复要慢很多。离线物理备份,从库中复制文件有什么用?为了提高备份效率,缩短备份时间,这也引出了第二种方案,直接对库文件进行物理备份。如上图所示,左侧数据库集群设置为1主2从架构。离线物理备份是如何实现的?第一步是从集群中移除一个从数据库并下线。又会有变化;第二步,scp拷贝库文件,即库的物理备份完成;文件拷贝完成后,库会挂回集群。使用离线物理备份的好处是备份和恢复都非常快。缺点也很明显:在备份过程中,从库无法继续提供在线服务。那么问题来了,有没有一种方案可以快速备份物理文件,继续提供在线服务呢?这是当今用于MySQL备份的最流行的PXB解决方案。什么是PXB?PXB的全称是PerconaXtraBackup。官网是这么说的:PXB是全球唯一开源免费的支持MySQL热备份的非阻塞备份工具。画外音:PerconaXtraBackup是世界上唯一开源、免费的MySQL热备份软件,可执行非阻塞备份工具。那么PXB是如何实现的:在库文件不断变化的情况下,让数据库持续提供在线服务;通过MySQL文件;to库文件的物理热备份呢?为了把问题说清楚,需要从redolog、LSN、MySQLcrash-recovery机制入手。1、redolog为什么会有redolog?事务提交后,事务对数据页的修改必须刷新(fsync)到磁盘,以保证事务的ACID特性。本次flush是随机写,随机写性能低。如果每次事务提交都刷新磁盘,会极大地影响数据库的性能。随机写性能差,有什么优化方法?架构设计中常见的优化方式有两种:先写日志(writelogfirst),将随机写优化为顺序写;将每次写入优化为批量写入;这个优化,用的是数据库。第一个优化是先把数据的修改按顺序写入日志,这个日志就是redolog。第二个优化是redolog的三层结构:logbuffer:应用层buffer;OS缓存:操作系统缓存;重做日志文件:物理文件;如果在某个时刻,数据库崩溃了,在刷新数据页之前,当数据库重启时,会重做重做日志中的内容,以保证将提交的事务对数据的影响刷新到磁盘中。总之,redolog是一种保证已提交事务的ACID特性,提高数据库性能的技术。2、redolog的格式从逻辑上讲,MySQL以行为单位管理数据;物理上,MySQL以页为单位管理数据,MySQL的缓冲池(buffer)机制也是以页为单位管理数据,事务提交后,不是每次都随机写入磁盘刷新数据页,而是为了提高通过顺序写入redolog来提高性能,那么redolog是不是直接保存了等待刷新的数据页呢?如果redolog直接把要flush的磁盘保存在datapage中,就会出现这样的问题。如果某条SQL语句只修改了一行记录中的一个属性,例如:updatesetsex=1wherename='shenjian'从物理上来说,实际只修改了1个字节。重做日志是不是真的会保存这个属性所在的所有页面数据(16K)?完全不是,redolog只需要记录:某个数据页(pagenum);一定的偏移位置(offset);某种类型的数据(类型);改成了什么值(value);这样,重做日志不仅可以实现以页为单位的顺序刷新数据,而且大大减小了日志的大小,其性能得到了进一步的提高。updatesetsex=1wherename='shenjian'还是以这条SQL为例,假设它修改了1234页,偏移量为5678,1个字节的数据,这个字节的性别由0变为1,那么,很容易认为redolog是类似这样的结构:这样当数据库crash时,如果bufferpool中的数据还没有来得及flush,就可以使用redolog保存1234页,偏移量为5678该处的1字节改成1,恢复数据。当然,MySQL会通过一系列的数据结构来管理redolog。重做日志的最小单位是一个512字节的数据块(block)。这个块由一个12字节的header,一个508字节的body,4字节的trailer组成,body中保存的是上面的数据页是如何被修改的记录。记录redolog的文件有几个,每个文件大小固定,循环使用。画外音:为了文中通俗易懂,本文尽量不提Mini-Transaction(mtr)的概念。3、LSN要讲redolog和故障恢复。LSN是一个绕不开的概念。什么是LSN?LSN,LogSequeueNumber,直译为日志序列号,是一个8字节的序列号,随着日志写入InnoDB只增不减。听起来像是日志序列号,但LSN不仅存储在重做日志中,它还存储在数据页中。画外音:缓冲池中的数据页和磁盘上的数据页都存储了LSN。存储在数据页(page)中的LSN可以用来标记数据页的“版本号”,记录数据页最后被修改的日志序列位置。例如,假设有两件事在逻辑上是连续执行的,并且都已提交:trx1:updatesetsex=0wherename='shenjian'redologlsn=1000trx2:updatesetsex=1wherename='shenjian'redologlsn=1001画外音:lsn已添加。同样假设第一个事务trx1已经被flush,但是第二个事务trx2还没有被flush,只写了redolog。画外音:最后一次刷新的页面,也就是最后一个检查点(checkpoint),也是通过LSN记录下来的,也会被写入到redolog中。这两个事务修改同一个数据页。很容易想到:磁盘数据页上的LSN=1000,redolog中有两条记录:第一条,redologlsn=1000第二条,redologlsn=1001为了提高性能数据库,数据库基本采用WAL(WriteAheadLog)方式,先写日志再刷磁盘,所以很容易想象磁盘数据页中的LSN会小于最新的重做日志中的LSN.画外音:此时redolog中记录的checkpoint也是1000,LSN有什么用?它与MySQL的崩溃恢复机制密切相关。4、InnoDB崩溃恢复(crash-recovery)这里的崩溃恢复指的是在MySQL异常退出然后重启之前恢复数据一致性的操作。画外音:从字面上翻译崩溃恢复可能更准确。InnoDB的崩溃恢复过程是怎样的?主要分为四个步骤:第一步,redolog操作:保证将提交事务影响的最新数据刷到数据页。第二步,undolog操作:保证未提交事务影响的数据页被回滚。第三步是合并写入缓冲区(changebuffer)。画外音:不是今天的重点。writebuffer的概念,详见《写缓冲(change buffer),这次彻底懂了!》。第四步是吹扫操作。画外音:InnoDB的一种垃圾回收机制,使用单独的后台线程定期处理索引中标记为删除的数据,不是今天的重点,以后可以详细讨论。第一步,redolog操作如何恢复最新的数据页?(1)从redolog中读取checkpointlsn,记录了最后一次flush的page,对应日志的LSN;(2)如果redolog中记录的logLSN小于checkpoint,说明相关数据已经flush,无需额外操作;(3)如果redolog中记录的日志LSN大于checkpoint,说明redolog中只写了相关数据,还来不及刷盘,需要redologon相关数据页,例如:将1234页偏移量5678处的1字节改为1,从而恢复数据。在崩溃恢复过程中,MySQL的启动日志更形象地说明了这一点:首先找到检查点;然后不断扫描大于checkpoint的redolog,不断恢复数据;画外音:redolog的LSN可以看到恢复过程。还有一点,redolog还有两个特点:一是幂等性,同一个redolog执行多次不影响数据恢复。其次,当从崩溃中恢复时,从早于检查点的LSN开始不会影响数据的最终一致性,因为一个数据页最终会被具有更大值的LSN日志恢复到最新的数据。5.PXB在线热备原理不知不觉写了上千字,差点忘了出处问题。PXB是如何实现的:保持数据库持续提供在线服务,当库文件不断变化时;通过MySQL文件;对库文件进行物理热备份?有了上面的大量铺垫,这个问题的答案就很容易了。首先,PXB启动一个线程,不断的监听redolog的增量,并将其复制到另一个文件中。之所以不能直接备份redolog,是因为redolog是循环使用的,PXB必须记录checkpointLSN之后的所有redolog。然后,PXB启动另一个线程,然后开始复制数据文件。复制数据文件的过程可能比较长,整个过程中数据文件可能不断被修改,导致数据不一致。不过没关系,所有的修改都已经在第一步记录下来了,额外记录的redolog。画外音:需要注意的是备份redolog的线程必须在开始备份数据文件之前启动,然后终止。最后通过备份数据文件,重放redolog,执行类似MySQL崩溃恢复过程的动作,将数据文件恢复到能保证一致性的checkpoint检查点。画外音:PXB还可以对非MySQL和非InnoDB进行在线热备份,这里不再展开。是不是很神奇!【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文