哪些特性对 MySQL 有性能优化(服务器场景)
🗄️ Linux 内核中对 MySQL 有性能优化的特性(服务器场景,完整列表)
核心观点
MySQL 性能优化的两大核心里程碑:原子写(Atomic Writes)消除 InnoDB 双写缓冲可带来 60-100% 的性能提升,io_uring 异步 I/O 框架替代传统 AIO 将每次 I/O 开销从微秒级降至纳秒级。此外调度器 EEVDF、页回收 MGLRU、文件系统 Fast Commit 等特性从不同维度为数据库场景提供系统性收益。
数据来源:LWN 2024 LSFMM 峰会和主线内核源码分析
一、🚀 原子写 / Untorn Writes(最高收益特性)
概述
NVMe/SATA 设备保证写入不撕裂(atomic/untorn write),MySQL 可安全关闭 InnoDB 双写缓冲(doublewrite buffer),消除 2× 写放大。
核心机制
| 维度 | 说明 |
|:—|:—|
| 系统调用标志 | RWF_ATOMIC (0x00000040) — pwritev2() 传参 |
| 限制条件 | 仅支持 O_DIRECT,长度必须为 2 的幂、自然对齐 |
| NVMe 实现 | 隐式保证:写长度 < 设备原子限制且不跨边界即自动原子 |
| SCSI 实现 | 需专用命令,不满足条件时直接拒绝 |
| XFS 实现 | xfs_atomic_write_cow_iomap_begin() — COW-based 软件原子写作为硬件回退 |
| ext4 实现 | ext4_map_blocks_atomic_write() — extent 层面的原子映射 |
MySQL 收益:60-100% 性能提升
Ted Ts’o 在 LSFMM 2024 明确表示:
“云厂商已经在为 MySQL 做 torn-write protection 广告了,他们用特定设置的 ext4 和能提供该保护的设备……该特性可为数据库提供 60-100% 的性能提升,因为 MySQL 可以避免做 double write。”
- InnoDB 双写缓冲原理:InnoDB 默认先写 2MB 双写缓冲区,再写实际数据文件——2× 写放大
- 原子写关闭双写:16KB 页写入被硬件保证不撕裂 → 直接写数据文件 → 写放大从 2× 降至 1×
- NVMe 16KB 撕裂边界:MySQL 的 16KB InnoDB 页恰好对齐 NVMe 的 16KB 自然撕裂边界
参考链接
| 资源 | 链接 | |:—|:—| | LWN LSFMM 2024 报道 | https://lwn.net/Articles/974953 | | XFS 原子写实现 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/xfs/xfs_file.c) | | ext4 原子写实现 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/ext4/file.c) |
二、⚡ io_uring 异步 I/O(次高收益特性)
SQPOLL(内核提交队列轮询)
IORING_SETUP_SQPOLL
- 内核线程持续轮询 SQ 队列,应用仅写共享环即可提交 IO
- 完全消除
io_uring_enter()系统调用开销 - 收益:MySQL 8.0+ 在 100K+ QPS 场景下,每笔 I/O 节省约 1-2µs 系统调用+上下文切换
IOPOLL / Hybrid IOPOLL
IORING_SETUP_IOPOLL // 纯轮询模式
IORING_SETUP_HYBRID_IOPOLL // 先轮询,超时后退回 IRQ(新增特性)
- 绕过 IRQ 中断路径,NVMe 直接返回完成
- Hybrid 模式:IO 延迟低时走轮询,延迟高时自动降级,适合 MySQL 波动负载
注册缓冲区 / 注册文件
IORING_REGISTER_BUFFERS // 固定内存映射,免去每 I/O 的 get_user_pages
IORING_REGISTER_FILES // 注册 fd,免去每 I/O 的 fget/fput
- 每次 I/O 节省约 1µs 的页引脚/释放开销
- MySQL InnoDB 的 I/O 密集场景收益显著
DEFER_TASKRUN
IORING_SETUP_DEFER_TASKRUN
- 延迟 task work 到 completion 时批量处理
- 减少 IPI 和 CPU 间通信开销
参考链接
| 资源 | 链接 | |:—|:—| | io_uring 核心实现 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (io_uring/io_uring.c) | | SQPOLL 实现 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (io_uring/sqpoll.c) | | Hybrid IOPOLL | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (include/uapi/linux/io_uring.h) |
三、📂 文件系统特性
3.1 ext4 Fast Commit(快速提交)
| 项目 | 说明 |
|---|---|
| 内核版本 | 主线已支持多年 |
| 原理 | TLV 格式记录操作(ADD_RANGE/DEL_RANGE/CREAT 等),仅记录元数据增量而非完整事务 |
| 触发 | EXT4_FEATURE_COMPAT_FAST_COMMIT,用 tune2fs -O fast_commit 启用 |
| MySQL 收益 | InnoDB 事务提交时 fsync 延迟从传统 jbd2 提交的 ~10ms 降至亚毫秒级(小事务场景) |
3.2 ext4 dioread_nolock
mount -o dioread_nolock
- DIO 读取未分配 extent 时不加锁
- 适合 MySQL 数据文件:InnoDB 写后立即读、双写缓冲写后读校验
3.3 XFS allocsize
mount -o allocsize=1m
- MySQL 核心配置:设置文件预分配大小为 1MB
- 防止 InnoDB 顺序写导致文件系统碎片化
- 对日志文件(ib_logfile)和数据文件的连续写入性能至关重要
3.4 XFS 延迟日志(CIL - Commit Item List)
- 批量归并日志条目后再提交,减少日志 I/O 次数
- 数据库写密集型负载:减少 fsync 调用频率约 50-70%
3.5 XFS Reflink / Always-COW
/sys/fs/xfs/debug/always_cow // 启用后写入一致不出洞
- 在线备份场景:
cp --reflink秒级 InnoDB 快照 - 数据库一致性备份不锁库
参考链接
| 资源 | 链接 | |:—|:—| | ext4 Fast Commit | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/ext4/fast_commit.c) | | XFS allocsize | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/xfs/xfs_super.c) |
四、🔧 块层特性
4.1 blk-mq 多队列
| 特性 | MySQL 优化场景 |
|---|---|
| 3 类 HW 队列 | Default/Read/Poll 分离,MySQL 的读写 I/O 走不同队列,互不干扰 |
| 多 HW 队列 | 多核 NUMA 架构下,每个核心就近提交到对应 NVMe 队列,避免锁竞争 |
| 轮询模式 (HIPRI) | 通过 IOCB_HIPRI 触发,NVMe 完成 DMA 后直接通知 CPU,跳过 IRQ |
4.2 I/O 调度器选择
| 设备类型 | 推荐调度器 | 原因 |
|:—|:—|:—|
| NVMe | none | 设备本身已并行化,调度器增加开销无收益 |
| SSD | mq-deadline | 防止 I/O 饥饿,优先 MySQL 读请求 |
4.3 Writeback Throttle(wbt)
# 数据库服务器建议关闭或大幅调高延时阈值
echo 0 > /sys/block/<dev>/queue/wbt_lat_usec
- 默认对非 NVMe 设备启用
- InnoDB 的 page cleaner 和 redo log 后台写可能被 wbt 误限流
- MySQL 场景必须关闭或调整
4.4 blk-iocost
/sys/fs/cgroup/io.cost.model
- cgroup2 IO 成本控制与 QoS
- 多 MySQL 实例共享存储时,按权重分配带宽,防止 “发疯的实例饿死邻居”
参考链接
| 资源 | 链接 | |:—|:—| | blk-mq | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (block/blk-mq.c) | | wbt | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (block/blk-wbt.c) | | blk-iocost | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (block/blk-iocost.c) |
五、🧠 内存管理特性
5.1 Multi-Gen LRU(MGLRU)
| 项目 | 说明 |
|---|---|
| 原理 | 4 代 LRU 替代传统双链 LRU,O(1) 回收候选选择 |
| look_around | 扫描年轻 PTE 周围页面并批量提升热页 |
| MySQL 收益 | 大内存数据库服务器(数百 GB)中,内存压力下回收延迟从毫秒级降至微秒级 |
| 适用场景 | OLTP 密集查询导致 InnoDB 有内存压力时;备份/DDL 触发大量页缓存回收时 |
5.2 zswap(压缩内存交换)
- 被换出的页先压缩存放在内存中,而非立即写盘
- MySQL 场景:如果 InnoDB buffer pool 以外的内存(如 tmp table 溢出、排序缓冲区)被换出,zswap 比磁盘 swap 快 10-100×
- 代价:压缩/解压 CPU 开销约 2-5%
六、⚙️ 调度器特性
服务器场景(非 RT)下调度器对 MySQL 的影响通常<5%,但在高并发多实例场景依然重要。
6.1 EEVDF 调度算法
- 内核 6.6+ 默认调度器,替代 CFS
- 按截止时间选择任务,更公平的 CPU 时间分配
- MySQL 场景:多实例(容器/VM)共享 CPU 时,EEVDF 比 CFS 延迟更均衡
6.2 Core Scheduling
/sys/kernel/debug/sched_debug 中的 core_sched_before
- SMT 超线程安全隔离:MySQL 实例不受同一物理核上其他不可信任务的影响
- 多 MySQL 容器在同一台物理机运行时,可以关闭 HT 替代方案(
offsibling损失的吞吐量回补约 30%)
6.3 Proxy Execution(代理执行)
- 持有 mutex 的线程可以将执行权捐赠给等待该 mutex 的线程
- MySQL 场景:
LOCK_system_mutex、LOCK_global_system_variables等全局锁竞争时,减少优先级反转
七、📄 预读(Readahead)
/sys/block/<dev>/queue/read_ahead_kb
| 场景 | 建议值 | 原因 |
|---|---|---|
| OLTP 随机读 | 0 或 4 |
MySQL 大部分是 16KB 随机读,预读会污染 InnoDB buffer pool |
| OLAP 全表扫描 | 256-1024 |
加速大量顺序数据读取 |
| 备份/DDL | 1024 |
提升 xtrabackup/ibbackup 读取速度 |
On-demand readahead 内核机制(mm/readahead.c):
- 流水线异步预读:每页消耗到
async_size即触发下一批 - MySQL 的连续 ib_logfile 写入场景收益
八、📊 MySQL 配置建议汇总表
| 特性 | 推荐配置 | 预期收益 |
|---|---|---|
| 原子写 | XFS + NVMe,开启 RWF_ATOMIC | 60-100%(关闭双写缓冲) |
| io_uring | MySQL 8.0+ 未开启则升级 | 20-40%(减少系统调用) |
| io_uring SQPOLL | 绑定 CPU 亲缘性 | 额外 10-15% |
| ext4 fast_commit | tune2fs -O fast_commit | 事务提交延迟从 10ms → <1ms |
| XFS allocsize=1m | mount -o allocsize=1m | 防止碎片化,持续写入性能稳定 |
| wbt 关闭 | echo 0 > wbt_lat_usec | 避免 InnoDB page cleaner 被限流 |
| read_ahead_kb=0 | OLTP 场景 | 防止缓存污染导致的 buffer pool thrashing |
| I/O 调度器 none | NVMe 设备 | 消除额外调度层开销 |
| MGLRU | 内核 6.1+ 默认 | 大内存回收延迟从 ms→µs |
| EEVDF | 内核 6.6+ 默认 | 多实例 CPU 分配更公平 |
九、🔗 完整参考链接
LWN 相关文章
| 文章 | 链接 | |:—|:—| | LWN: LSFMM 2024 - Atomic writes | https://lwn.net/Articles/974953 | | LWN: The Rotating Staircase Deadline Scheduler | https://lwn.net/Articles/225135 | | LWN: On-demand readahead | https://lwn.net/Articles/235620 | | LWN: Shared pain (fsync/ext3 性能讨论) | https://lwn.net/Articles/478135 | | LWN: 主页 | https://lwn.net |
内核源码主线
| 模块 | commit/路径 | |:—|:—| | 原子写系统调用 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (include/uapi/linux/fs.h) | | io_uring 核心 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (io_uring/) | | ext4 fast_commit | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/ext4/fast_commit.c) | | XFS 原子写 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (fs/xfs/xfs_file.c) | | blk-mq | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (block/blk-mq.c) | | wbt | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (block/blk-wbt.c) | | MGLRU | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (mm/vmscan.c) | | EEVDF | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=master (kernel/sched/fair.c) |
一句话总结
当前 Linux 内核中 MySQL 服务器场景的三大核心收益来源:原子写(60-100% 收益,关闭双写缓冲)、io_uring(20-40% 收益,消除系统调用开销)、文件系统配置调优(ext4 fast_commit / XFS allocsize 可降低事务延迟和碎片化)。 其余特性(MGLRU、EEVDF、blk-mq 等)提供辅助性但不可忽视的稳定性增益。
参考来源
本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。