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

本文涉及的产品
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 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),只有那些需要做崩溃恢复的文件,才会被打开。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
23天前
|
关系型数据库 MySQL
MySQL自增ID用完会怎样?
MySQL自增ID用完会怎样?
|
4天前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
27天前
|
关系型数据库 MySQL 应用服务中间件
win7系统搭建PHP+Mysql+Apache环境+部署ecshop项目
这篇文章介绍了如何在Windows 7系统上搭建PHP、MySQL和Apache环境,并部署ECShop项目,包括安装配置步骤、解决常见问题以及使用XAMPP集成环境的替代方案。
37 1
win7系统搭建PHP+Mysql+Apache环境+部署ecshop项目
|
29天前
|
数据可视化 关系型数据库 MySQL
Mysql8 如何在 Window11系统下完成跳过密钥校验、完成数据库密码的修改?
这篇文章介绍了如何在Windows 11系统下跳过MySQL 8的密钥校验,并通过命令行修改root用户的密码。
Mysql8 如何在 Window11系统下完成跳过密钥校验、完成数据库密码的修改?
|
25天前
|
关系型数据库 MySQL Linux
【Azure 应用服务】在创建Web App Service的时候,选Linux系统后无法使用Mysql in App
【Azure 应用服务】在创建Web App Service的时候,选Linux系统后无法使用Mysql in App
【Azure 应用服务】在创建Web App Service的时候,选Linux系统后无法使用Mysql in App
|
29天前
|
关系型数据库 MySQL 数据库连接
成功解决「MySQL问题1」启动mysql时:发生系统错误5拒绝访问
这篇文章介绍了如何解决启动MySQL服务时遇到的系统错误5(拒绝访问),通过管理员权限启动命令窗口并使用"net start mysql"和"net stop mysql"命令来控制服务。
|
29天前
|
存储 SQL 关系型数据库
mysql体系结构及主要文件
了解MySQL的体系结构和它的主要文件,能够帮助数据库管理员和开发者更好地管理和优化数据库。这对于数据库的正常运行、性能优化、数据恢复和系统维护来说是至关重要的。通过对这些组件的深入理解,可以更容易地解决数据库问题,并在必要时定制或调整数据库的行为以满足特定的应用需求。
39 0
|
30天前
|
SQL 关系型数据库 MySQL
【MySQL核心】MySQL无法启动?批量恢复MySQL 物理文件-拯救即将跑路的你
【MySQL核心】MySQL无法启动?批量恢复MySQL 物理文件-拯救即将跑路的你
|
3天前
|
存储 SQL 关系型数据库
使用MySQL Workbench进行数据库备份
【9月更文挑战第13天】以下是使用MySQL Workbench进行数据库备份的步骤:启动软件后,通过“Database”菜单中的“管理连接”选项配置并选择要备份的数据库。随后,选择“数据导出”,确认导出的数据库及格式(推荐SQL格式),设置存储路径,点击“开始导出”。完成后,可在指定路径找到备份文件,建议定期备份并存储于安全位置。
54 11
|
23天前
|
弹性计算 关系型数据库 数据库
手把手带你从自建 MySQL 迁移到云数据库,一步就能脱胎换骨
阿里云瑶池数据库来开课啦!自建数据库迁移至云数据库 RDS原来只要一步操作就能搞定!点击阅读原文完成实验就可获得一本日历哦~

相关产品

  • 云数据库 RDS MySQL 版