redo log文件是在文件末尾串行追加对数据页(内存page)的修改记录,是一种WAL;undo log是和普通table一样存在于buffer_pool和硬盘的数据行。
利用undo数据,建立全库快照,在全库快照中进行数据检索
1、在一个事务开始查询的时候,会获取当前最大的已完成的事务提交序号(Transaction Serialization Number),记为这个事务的low_limit_no(可重复读隔离级别下,事务的所有语句都使用第一个语句执行前获取的low_limit_no)
2、当检索到的table data的数据行未提交,或者数据行的事务提交序号大于low_limit_no,则去unbo里获取对应历史数据
3、当undo里的数据行的事务提交序号小于所有在线事务的low_limit_no,则可以清理
P.S. 事务提交序号(Transaction Serialization Number)不是事务ID,事务ID是事务开始时分配的,提交序号是提交时才分配的并且会记录到数据行附属信息里
1、修改buffer_pool里的table数据页和undo数据页,同时修改数据页附属信息里的的当前Log Sequence Number(LSN)
2、对上述两类数据页的修改记录写入redo log buffer,一行一个LSN
3、commit时,把redo log buffer的内容追加写入到redo log文件,但此时文件脏数据还仅存在于os buffer里
4、每秒强制刷新os buffer里的redo log脏数据页到硬盘(innodb_flush_log_at_trx_commit=2,存在单节点数据遗失风险,但可配合半同步复制来实现数据保障)
5、redo文件写满时、buffer pool里脏数据页达到50%(innodb_max_dirty_pages_pct=50)时,会刷新到硬盘上的table data文件;并把刷盘开始时redo文件的位置记为checkpoint,表示之前的记录已可舍弃
1、从上次checkpoint开始检查每行redo log
2、如果硬盘对应数据页的当前LSN小于日志行的LSN,则应用redo log,并修改数据页附属信息里的当前LSN
3、redo log检查完毕后,使用undo记录回滚未commit的table数据行、清空undo记录,checkpoint变更为redo log末尾
4、数据库开始提供服务
掌握备份原理,才能理解备份工具各个参数的作用
MyDumper主要利用undo,实现整库快照的导出
1、一个主线程执行FLUSH TABLES WITH READ LOCK,将脏数据页刷新到table data文件并获得只读锁(等待现有查询、修改操作完成,并阻塞新发起的所有数据库操作;所以不要在master库进行逻辑备份,除非有业务静默期)
2、主线程获取当前binlog位置
3、默认4个子线程执行START TRANSACTION WITH CONSISTENT SNAPSHOT,获取到同一个low_limit_no(当前最大的事务提交序号)
4、主线程执行UNLOCK TABLES(数据库恢复所有功能)
5、子线程并发导出数据(备份的就是之前那个low_limit_no对应的全库快照)
P.S. 之所以一定要获取精确的binlog位点,是为了建立数据一致的slave、恢复master到指定时间点等目的
XtraBackup主要利用redo,通过类似宕机恢复的过程,把复制的数据文件同步到redo记录的最终状态
1、执行LOCK INSTANCE FOR BACKUP,阻止数据结构的修改(mysql8)
2、记录当前redo的checkpoint,并在备份全程实时获取之后追加的所有记录
3、复制table data目录(这个过程中,目录里的文件还在被不断修改)
4、查询log_status系统表,mysql会触发binlog、redo的落盘,再把binlog和redo两个日志的一致性位点作为返回结果(备份的就是这个位点对应的全库快照;如果数据库当前版本不支持此机制,比如maraidb至2022年的全部版本,则退化到执行FLUSH TABLES WITH READ LOCK,引发全库阻塞)
5、UNLOCK INSTANCE(可以执行DDL语句了)
6、应用redo到复制好的table data(通过数据页附属信息里的当前LSN,可以判断redo记录是否需要在此数据页上重放)
1、导入备份到空白数据库(逻辑备份不含账号、权限信息)
2、由于备份里已包含快照对应的master binlog位点信息,只要手动设置master地址和有权限获取binlog的账号+密码,即可从此binlog位点开始同步
1、从原slave制作备份时,加上–slave-info参数,导出原slave已同步的master binlog的位点记录,而不是使用原slave本身的binlog位点(触发执行FLUSH TABLES WITH READ LOCK)
2、后续步骤同上,即可实现新旧两个slave连接到同一个master
用于master数据库执行未知sql造成了数据破坏,并通过binlog同步破坏了所有slave的场景
1、导入备份到空白数据库(如果是从slave制作的备份,需包含–slave-info)
2、找到备份里的master binlog位置信息,作为初始位置
3、使用mysqlbinlog命令行工具检查原binlog文件,找到一个位置作为恢复的终止位置
4、因为每行数据变更前+变更后的明细全部存在于binlog里,所以binlog工具可以把两个位置之间的binlog转化为更新数据的sql
5、在新节点执行sql