MySQL8.0新特性:增加系统文件追踪space ID和物理文件的映射

简介: Note1: 本文所有代码相关的内容都是基于MySQL8.0.3,而目前版本还处于RC和快速开发的状态,不排除后面的版本逻辑,函数名等发生变化。Note2: 主要代码在这个commit 中,感兴趣的也可以自行阅读代码Note3: 本文仅是本人的阅码笔记,记录的比较凌乱。

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),只有那些需要做崩溃恢复的文件,才会被打开。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
3月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
2月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
505 5
|
3月前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
156 15
|
3月前
|
关系型数据库 MySQL 数据库
MySql事务以及事务的四大特性
事务是数据库操作的基本单元,具有ACID四大特性:原子性、一致性、隔离性、持久性。它确保数据的正确性与完整性。并发事务可能引发脏读、不可重复读、幻读等问题,数据库通过不同隔离级别(如读未提交、读已提交、可重复读、串行化)加以解决。MySQL默认使用可重复读级别。高隔离级别虽能更好处理并发问题,但会降低性能。
179 0
|
7月前
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
537 17
|
6月前
|
SQL 关系型数据库 MySQL
MySQL 5.6/5.7 DDL 失败残留文件清理指南
通过本文的指南,您可以更安全地处理 MySQL 5.6 和 5.7 版本中 DDL 失败后的残留文件,有效避免数据丢失和数据库不一致的问题。
|
8月前
|
关系型数据库 MySQL Linux
CentOS 7系统下详细安装MySQL 5.7的步骤:包括密码配置、字符集配置、远程连接配置
以上就是在CentOS 7系统下安装MySQL 5.7的详细步骤。希望这个指南能帮助你顺利完成安装。
2066 26
|
8月前
|
安全 关系型数据库 MySQL
MySQL8使用物理文件恢复MyISAM表测试
MySQL8使用物理文件恢复MyISAM表测试
168 0
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
165 3

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多