update:从8.0.11开始,又改成了打开全部ibd文件,但是改成了并行扫描

Note1: 本文所有代码相关的内容都是基于MySQL8.0.3,而目前版本还处于RC和快速开发的状态,不排除后面的版本逻辑,函数名等发生变化。

Note2: 主要代码在这个commit 中,感兴趣的也可以自行阅读代码

Note3: 本文仅是本人的阅码笔记,记录的比较凌乱。。。

前面我们提到了MySQL5.7的几个崩溃恢复产生的性能退化 为了解决崩溃恢复的效率问题, MySQL8.0对crash recovery的逻辑进行了进一步的优化。 在之前的版本中,InnoDB通过向redo log中写入日志来追踪在一次checkpoint后修改过的表空间信息,这样就无需在crash recovery时打开所有的表空间,只需搜集哪些被影响到的表空间。而到了8.0新版本里,采用了一种全新的方式:单独创建了系统映射文件, 将space id及路径信息轮换着写到两个指定的系统文件tablespaces.open.1 and tablespaces.open.2中(ref Fil_Open::write)

实现的思路其实不复杂,就是将所有的表空间ID和对应的路径信息存储到系统文件中,在崩溃恢复时再按需打开。

系统文件更新

那么如何保证所有的表空间信息都一个不漏的存储到系统文件了呢 ? 实际上他跟踪了所有的表空间文件操作,并更新内存cache中(Fil_Open::m_spaces), 如下:

a. fil_node_open_file

fil_system->m_open.enter();

fil_system->m_open.log(node->space->id, node->name);

fil_system->m_open.exit();

打开表空间文件后,写一条日志MLOG_FILE_OPEN, 并将表空间状态 Nodes::OPEN以及日志end lsn在内存中进行更新(Fil_Open::Nodes::load)

b. fil_node_close_file

fil_system->m_open.enter();

fil_system->m_open.close(node->space->id, node->name);

fil_system->m_open.exit();

关闭表空间文件后, 将缓存的表空间信息LSN重置为0,并将状态设置为CLOSED (Fil_Open::Nodes::close)

c. fil_name_write_rename

fil_system->m_open.enter();

fil_system->m_open.log(space_id, new_name);

fil_system->m_open.to_file();

fil_system->m_open.exit();

在物理rename文件之前, 将新的表空间名通过MLOG_FILE_OPEN写到redo log中,记录新文件的状态到内存。

随后就将缓存的表空间信息写到系统映射文件中(Fil_Open::to_file)

d. fil_delete_tablespace

fil_system->m_open.enter();

fil_system->m_open.deleted(id);

fil_system->m_open.exit();

在物理删除文件之后,将对应的表空间状态设置为DELETED (Fil_Open::deleted)

e. fil_ibd_create

fil_system->m_open.enter();

fil_system->m_open.open(space_id, file->name, log_get_lsn());

fil_system->m_open.exit();

在物理创建表空间文件之后, 调用Fil_Open::open 将新文件的信息存储到内存中。同样的包含创建文件时的LSN

可见InnoDB在对文件进行打开,关闭,创建,删除,重命名这些操作时都进行了追踪,其中CREATE/DELETE/RENAME的cache更新均发生在记录对应的MLOG_FILE_*日志之前。

另外我们也可以看到,表空间信息不是直接写入的,而是经过zip压缩后再写的,以减少磁盘空间占用。

那么何时将缓存的信息刷到磁盘呢 ?

第一种情况是rename tablespace时,会做一次写文件

第二种情况是做checkpoint之前会去做一次flush(fil_tablespace_open_sync_to_disk), 相比第一种情况,这里先做一次清理(Fil_Open::purge -> Fil_Open::Nodes::purge),将状态为DELETED/MISSING的无效表空间记录删除掉,再刷到磁盘

当系统正常关闭时,InnoDB会去将系统文件中的信息全部清除掉(fil_tablespace_open_clear),因为崩溃恢复无需用到。

崩溃恢复

那么崩溃恢复时,如何使用该文件呢?

首先在启动时(srv_start), 当确定了需要崩溃恢复时(recv_recovery_from_checkpoint_start),就会去从系统映射文件中载入表空间信息到内存中(fil_tablespace_open_init_for_recovery --> Fil_Open::from_file)。

随后开始读redo log并解析, 如下堆栈:

recv_recovery_begin

|--> recv_scan_log_recs

|--> recv_parse_log_recs

|--> recv_single_rec

|--> recv_multi_rec

在将redo log加入到hash table之前,会先进行判断,只有在文件中找到的表空间,才需要去apply日志。

if (space_id == TRX_SYS_SPACE

|| fil_tablespace_lookup_for_recovery(space_id)) {

recv_add_to_hash_table(

type, space_id, page_no, body,

ptr + len, old_lsn, recv_sys->recovered_lsn);

} else {

recv_sys->missing_ids.insert(space_id);

}

由于系统文件不是实时flush的,因此在解析到MLOG_FILE_*类型的redo时, 也要对缓存的表空间信息进行修正(fil_tablespace_name_recover --> fil_name_process_for_recovery) ,以确保所有需要apply redo的tablespace都load到内存中。

在执行崩溃恢复时,InnoDB会按需去打开表空间文件,然后再去apply日志。(recv_apply_hashed_log_recs --> fil_tablespace_open_for_recovery),只有那些需要做崩溃恢复的文件,才会被打开。

mysql space id_MySQL8.0新特性:增加系统文件追踪space ID和物理文件的映射-阿里云开发者社区...相关推荐

  1. mysql自定义函数的分号_MySQL 第八篇:自定义函数、存储过程、游标-阿里云开发者社区...

    我把MySQL的内容整理成9篇博客,学完这9篇博客虽不能说能成为大神,但是应付一般中小企业的开发已经足够了,有疑问或建议的欢迎留言讨论. 自定义函数 一.函数的概念与定义 1.理解函数 函数可以看作是 ...

  2. mysql auto position_MySQL内核月报 2015.01-MySQL · 捉虫动态· 设置 gtid_purged 破坏AUTO_POSITION复制协议-阿里云开发者社区...

    bug描述 Oracle 最新发布的版本 5.6.22 中有这样一个关于GTID的bugfix,在主备场景下,如果我们在主库上 SET GLOBAL GTID_PURGED = "some_ ...

  3. mysql数据库增删改查关键字_Mysql数据库,增删改查笔记(非常重要)-阿里云开发者社区...

    新增数据: INSERT 语法: INSERT [INTO] [列名] VALUES; INSETR INTO 表名(列名1,列名2) VALUES(值1,值2); 如果INSETR语句中不写列名,则 ...

  4. gossip 区块链_区块链教程Fabric1.0源代码分析流言算法Gossip服务端一兄弟连区块链教程-阿里云开发者社区...

    区块链教程Fabric1.0源代码分析流言算法Gossip服务端一,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁.回归理性,表面上看相关人才需求与身价似乎正在回落.但事实上,正是初期泡沫的渐退 ...

  5. subsonic 3.0 mysql_SubSonic3.0使用外连接查询时查询不出数据的问题修改-阿里云开发者社区...

    今天在开发时,要使用到外连接查询,如图 老是查不出数据,所以就追踪了一下代码,发现查询后生成的SQL语句变成了内连接了,真是晕 然后继续Debug,发现原来SqlQuery类在调用LeftInnerJ ...

  6. mysql join 索引 无效_ORACLE MYSQL中join 字段类型不同索引失效的情况-阿里云开发者社区...

    ORACLE MYSQL中join 字段类型不同索引失效的情况 重庆八怪 2016-12-29 780浏览量 简介: 关于JOIN使用不同类型的字段类型,数据库可能进行隐士转换,MYSQL ORACL ...

  7. mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区

    关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...

  8. freebsd mysql 安装_Freebsd中mysql安装及使用笔记-阿里云开发者社区

    Freebsd中mysql安装及使用笔记 x3d 2009-07-31 662浏览量 简介: 1.安装 一开始连mysql的软件包在freebsd中叫什么都不知道: 依稀属于databases类,先到 ...

  9. mysql sdi_MySQL 8.0新特性: 数据字典

    一.概述 数据字典(Data Dictionary)中存储了诸多数据库的元数据信息,包括基本Database, table, index, column, function, trigger, pro ...

最新文章

  1. EST | 系统评价污水样品中选定药物、非法药物及其代谢物的稳定性
  2. 使用Windows Azure创建移动服务
  3. 细说SSO单点登录(转)
  4. STM32 HAL库 串口DMA(收发)和STM32串口中断接收(接收时间管理机制)+ESP8266 wifi模组通信问题
  5. 基于TCP协议的通信模型
  6. Oracle任务调度的高级选项
  7. 方立勋_30天掌握JavaWeb_Cookie
  8. CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告
  9. 【直播预告】创享未来 2016微软开发者峰会
  10. BFS HDOJ 1242 Rescue
  11. Unieap3.5-Grid编辑列中数字与下拉改变
  12. pandas操作手册
  13. python 高等数学实验_高等数学——基于Python的实现
  14. 笔记本连接无线蓝牙缺少驱动解决方法
  15. ov5640帧率配置_基于OV5640的FPGARAM HDMI显示
  16. dalong(大龙燚火锅)
  17. 徐思201771010132《面向对象程序设计(Java)》第十二周学习总结
  18. 推荐一个可以倍速播放HTML5视频的脚本
  19. 拿到别人提供的虚拟机需要做的几件事情
  20. Flex应用启动背后的故事

热门文章

  1. Python PCA降维小例子
  2. 搭建远程jupyter服务器并从本地连接,有浏览器的地方就有Python!
  3. java 反应堆模式_Netty中的三种Reactor(反应堆)
  4. Java怎么跑不起来_tarsJava example 跑不起来
  5. [BZOJ1059][ZJOI2007]矩阵游戏
  6. java框架之SpringCloud(2)-Rest微服务案例
  7. 如何禁止chrome浏览器http自动转成https 【转】
  8. 关于安装AccessDatabaseEngine_x64.exe 的说明
  9. Hibernate学习笔记_查询
  10. 测试Word2013发布博客