点一下关注吧!!!非常感谢!!持续更新!!!
🚀 AI篇持续更新中!(长期更新)
AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kimi‑K2开源大模型解读与实践,持续打造实用AI工具指南!📐🤖
💻 Java篇正式开启!(300篇)
目前2025年07月28日更新到:
Java-83 深入浅出 MySQL 连接、线程、查询缓存与优化器详解
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!
📊 大数据板块已完成多项干货更新(300篇):
包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解
新版本演化
MySQL 5.7 存储引擎优化
Undo 日志表空间改进
MySQL 5.7 将 Undo 日志表空间从共享的 ibdata 文件中独立出来,这项改进带来了以下优势:
- 用户可以灵活配置 Undo 表空间的数量和大小,通过参数
innodb_undo_tablespaces
设置表空间数量(默认0,范围0-128) - 支持独立管理 Undo 空间,避免 ibdata 文件过大导致的性能问题
- 每个 Undo 表空间默认初始大小为10MB,可通过
innodb_undo_directory
指定存储路径 - 实际应用场景:当系统需要支持大量并发事务时,可以配置多个 Undo 表空间减少争用
Temporary 临时表空间
新增的临时表空间特性包含以下改进:
- 通过独立的临时表空间文件(ibtmp1)存储临时表数据
- 默认存储在数据目录,可通过
innodb_temp_data_file_path
配置路径和大小 - 支持存储临时表、排序缓存等临时数据
- 实际应用:大表排序操作会优先使用临时表空间而非内存,避免内存溢出
- 注意:该文件会随使用增长,需要定期监控其大小
动态 Buffer Pool 调整
Buffer Pool 内存管理的重要改进:
- 支持通过
SET GLOBAL innodb_buffer_pool_size=X
在线调整大小(单位字节) - 调整过程分为多个区块(chunk)逐步完成,避免性能剧烈波动
- 建议调整幅度不超过当前大小的1倍,且总大小不超过物理内存的80%
- 监控命令:
SHOW STATUS LIKE 'Innodb_buffer_pool_resize_status'
- 应用场景:业务高峰期可临时扩大缓冲池,低谷期可缩小以释放内存资源
这些改进显著提升了 MySQL 5.7 的运维灵活性和性能表现,使数据库管理员可以更灵活地根据业务需求进行资源配置。
MySQL 8.0 存储架构优化
InnoDB 表空间分离
MySQL 8.0 对 InnoDB 存储引擎进行了重大架构改进,将数据字段(data)和Undo日志从共享表空间ibdata中完全分离。在之前的版本中,必须保持ibdata中的数据字典与独立表空间(.ibd文件)中的数据字段严格一致。而8.0版本通过重构存储架构,消除了这一限制,大大提升了管理的灵活性和可靠性。
临时表空间增强
MySQL 8.0 对临时表空间进行了多项改进:
- 支持配置多个物理文件作为临时表空间
- 所有临时表均使用InnoDB存储引擎
- 支持在临时表上创建索引
这些改进显著提升了复杂查询、排序操作和临时表处理的性能。例如,在大数据量排序时,优化后的临时表空间可以更高效地处理临时数据。
表空间管理优化
MySQL 8.0 引入了类似Oracle的表空间管理功能:
- 用户可以创建多个表空间,每个表空间可以包含多个物理数据文件
- 一个表空间可以被多个表共享使用
- 但每个表只能存放在一个特定的表空间中
这种架构允许更灵活的存储管理,例如可以将不同业务的数据分配到不同的表空间,或者将热数据单独存放以优化I/O性能。
Doublewrite Buffer 分离
MySQL 8.0 将 Doublewrite Buffer 从共享表空间ibdata中分离出来,形成了一个独立的存储区域。这个改进带来了以下优势:
- 减少了ibdata文件的I/O压力
- 提高了崩溃恢复的效率
- 允许对Doublewrite Buffer进行独立的配置优化
Doublewrite Buffer是InnoDB确保数据页完整性的重要机制,分离后可以更好地发挥其作用。
InnoDB 线程模型
IO Thread 详解
InnoDB 存储引擎为了提高数据库的并发性能,采用了异步IO(AIO)机制来处理各种读写操作。这种设计可以显著降低I/O等待时间,提高整体吞吐量。
IO Thread 的发展历史
- 早期版本(1.0之前):InnoDB 使用4个固定的IO线程:
- 1个 write thread
- 1个 read thread
- 1个 insert buffer thread
- 1个 log thread
- 1.0版本之后:为了进一步提升性能,将 read thread 和 write thread 的数量都扩展到了4个,使总线程数增加到10个。这种扩展能够更好地处理高并发的读写请求。
各线程的详细功能
1. Read Thread
- 数量:4个(默认)
- 主要职责:负责从磁盘读取数据页到缓冲池(Buffer Pool)
- 具体工作流程:
- 当查询需要访问不在缓冲池中的数据页时
- read thread 从磁盘读取相应页到内存
- 数据页被加载到缓冲池后供SQL线程使用
- 性能影响:多个read thread可以并行处理读请求,减少读操作的等待时间
2. Write Thread
- 数量:4个(默认)
- 主要职责:将缓冲池中的脏页(修改过的页)刷新到磁盘
- 具体工作流程:
- 当页在缓冲池中被修改后标记为脏页
- 根据刷新策略(如LRU或flush list),write thread 将脏页写入磁盘
- 写入完成后清除脏页标记
- 性能影响:多个write thread可以并行刷盘,避免单个线程成为性能瓶颈
3. Log Thread
- 数量:1个
- 主要职责:负责重做日志(redo log)缓冲区的刷新
- 具体工作流程:
- 事务提交时产生redo log记录
- log thread 将redo log从日志缓冲区刷新到磁盘文件
- 确保事务的持久性(Durability)
- 关键特性:采用顺序写方式,性能较高,对事务提交速度有重要影响
4. Insert Buffer Thread
- 数量:1个
- 主要职责:处理变更缓冲(Change Buffer)的合并操作
- 具体工作流程:
- 对非唯一二级索引的修改首先写入change buffer
- 当相关页被读取时,insert buffer thread 将change buffer中的修改合并到数据页
- 定期将change buffer的内容刷新到磁盘
- 性能优势:减少随机IO,特别适合写多读少的场景
配置参数
可以通过以下参数调整IO线程数量:
innodb_read_io_threads
:控制read thread数量(默认4)innodb_write_io_threads
:控制write thread数量(默认4)
实际应用场景
在高并发OLTP系统中:
- 读密集型应用可以适当增加read thread数量
- 写密集型应用可以增加write thread数量
- 对于大量非唯一索引更新的场景,insert buffer thread能显著提升性能
- log thread对事务提交性能至关重要,需要确保redo log所在的磁盘有良好的顺序写性能
这些IO线程协同工作,共同构成了InnoDB高效处理I/O操作的基础架构。
Purge Thread
InnoDB 存储引擎中的 Purge Thread 是一个后台线程,主要负责清理已经完成事务的 undo 日志。当事务提交后,这些 undo 日志就不再需要了,因为它们已经完成了回滚或 MVCC(多版本并发控制)的历史记录功能。Purge Thread 会定期扫描 undo 日志空间,回收那些可以被重用的 undo 页。
工作原理
- 当事务提交后,InnoDB 会在 undo 日志中标记这些记录为"可清除"状态
- Purge Thread 会周期性地检查这些标记
- 对于确定不再需要的 undo 日志,Purge Thread 会释放对应的存储空间
- 被释放的 undo 页会被放入空闲列表,供新事务重用
配置参数
可以通过以下 SQL 命令查看 Purge Thread 的相关配置:
show variables like '%innodb_purge_threads%'
这个命令会显示以下重要参数:
innodb_purge_threads
: 指定 Purge Thread 的数量(默认为4)innodb_purge_batch_size
: 每次清理的 undo 日志数量
性能优化
在以下场景中可能需要调整 Purge Thread 配置:
- 高并发写入系统:可以适当增加线程数量
- 大数据量事务:可能需要增大 batch size
- 系统空闲时段:可以降低线程数量以节省资源
Purge Thread 的高效运作对 InnoDB 存储引擎的整体性能至关重要,它确保了 undo 日志空间的及时回收,避免了存储空间的浪费和性能下降。
对应的内容如下:
Page Cleaner Thread
Page Cleaner Thread 是 InnoDB 存储引擎中的一个重要后台线程,主要负责将缓冲池中的脏页(Dirty Page)刷新到磁盘。这个线程在数据库性能调优中起着关键作用。
主要功能细节
-
脏页刷新机制:
- 周期性地检查缓冲池中的脏页
- 根据脏页比例和系统负载决定刷新速率
- 采用自适应刷新算法,避免I/O突发
-
与Redo Log的关系:
- 脏页刷盘后,对应的redo log就可以被覆盖
- 实现了redo log的循环使用机制
- 确保数据持久性和崩溃恢复能力
工作流程
- 扫描缓冲池中的脏页列表
- 计算需要刷新的脏页数量(考虑系统负载)
- 调用write thread线程执行实际的I/O操作
- 更新相关元数据信息
配置参数
可以通过以下SQL查看和设置相关参数:
-- 查看当前配置的Page Cleaner线程数量
show variables like '%innodb_page_cleaners%';
-- 其他相关参数
show variables like '%innodb_lru_scan_depth%';
show variables like '%innodb_io_capacity%';
最佳实践
- 在多核服务器上,可以适当增加page cleaner线程数
- 通常建议设置为CPU核心数的1/4到1/2
- 需要平衡I/O能力和CPU资源消耗
监控指标
可以通过以下方式监控Page Cleaner的工作状态:
-- 查看刷新统计信息
show engine innodb status\G
-- 查找"BUFFER POOL AND MEMORY"部分
对应的内容如下所示:
Master Thread
InnoDB 的主线程(Master Thread)是存储引擎的核心调度线程,负责协调和管理其他后台线程的工作,在 MySQL 服务器中拥有最高优先级。其主要职责是将内存缓冲池(Buffer Pool)中的修改数据异步刷新到磁盘文件,确保内存数据与磁盘数据的最终一致性,同时维持数据库的高性能运行。
主要功能模块包括:
- 脏页刷新(page cleaner thread):负责将修改过的数据页(dirty page)写入磁盘
- undo 页回收(purge thread):清理不再需要的undo日志页
- redo 日志刷新(log thread):将redo日志缓冲区内容持久化到磁盘
- 写缓冲合并(change buffer merge):合并对二级索引的变更操作
Master Thread 采用周期性任务调度机制,主要包含两个处理周期:
每秒执行的操作(每秒触发一次):
-
日志缓冲区刷新:
- 将redo log buffer中的内容刷新到磁盘redo log文件
- 确保事务的持久性(Durability)
- 示例:当事务提交时,虽然数据页可能还在内存中,但redo log已持久化
-
写缓冲区合并:
- 根据当前系统I/O压力动态调整合并策略
- 将change buffer中缓存的二级索引变更应用到磁盘
- 应用场景:对非唯一索引的DML操作可先缓存在change buffer中
-
脏页刷新:
- 当缓冲池中脏页比例达到innodb_max_dirty_pages_pct(默认75%)时触发
- 采用自适应刷新算法,避免I/O突发
- 例如:当系统负载较低时可能提前刷新脏页
每10秒执行的操作(每10秒触发一次):
-
强制脏页刷新:
- 无论脏页比例如何,都会刷新一定数量的脏页
- 防止长时间未刷新导致恢复时间过长
-
全量写缓冲区合并:
- 执行完整的change buffer合并操作
- 确保长时间运行的更新操作最终被应用
-
日志缓冲区强制刷新:
- 保证即使没有事务提交,redo log也能定期持久化
- 为潜在的崩溃恢复提供更多保障
-
undo页清理:
- 删除不再需要的旧版本数据(undo页)
- 通过purge操作回收存储空间
- 例如:当事务提交且没有其他事务需要读取旧版本时
注意:在MySQL 5.6+版本中,许多功能已拆分为独立的后台线程(如page cleaner thread),但Master Thread仍负责整体协调工作。