6.4 操作系统内核调优


6.4 操作系统内核调优

本节摘要:数据库跑在 OS 上,OS 内核参数影响性能。本节讲清楚文件句柄、swap、大页、IO、内核参数调优,让 OS 不拖数据库后腿。

OS 对数据库的影响

数据库依赖 OS:

  • 文件 IO——OS 文件系统、IO 调度。
  • 内存管理——OS 页缓存、swap。
  • 进程/线程——OS 调度。
  • 网络——OS TCP 栈。

OS 参数不当:

  • 文件句柄不够——连接/打开文件失败。
  • swap——内存换页严重退化。
  • 大页未用——TLB miss 多。
  • IO 调度差——IO 延迟高。

文件句柄

数据库打开多文件(数据文件、日志、连接 socket)。

问题:句柄不够——"Too many open files" 错误,连接/查询失败。

调优

  • 临时:ulimit -n 65535(当前会话)。
  • 永久:/etc/security/limits.conf
    * soft nofile 65535 * hard nofile 65535 mysql soft nofile 100000 postgres soft nofile 100000
  • 系统级:/proc/sys/fs/file-max——系统总句柄上限,调大(如 1000000)。
  • 验证:cat /proc/sys/fs/file-nr——当前/已用/上限。

原则:句柄宁多勿少,但注意每句柄占内存(小)。

swap 与内存

swap:内存不够时把页换到磁盘,严重退化(磁盘比内存慢 10 万倍)。

调优

  • swappiness:/proc/sys/vm/swappiness(0-100)。
    • 100——积极用 swap。
    • 0——尽量不用 swap(仍可能在极端 OOM 时用)。
    • 数据库设 1-10(尽量不用 swap,但不完全禁防 OOM 杀进程)。
    • echo 1 > /proc/sys/vm/swappiness
  • /etc/sysctl.conf:vm.swappiness=1(永久)。

原则:数据库不用 swap——加内存而非靠 swap。swappiness 调低,监控 swap 使用,高则加内存。

OOM Killer

  • 内存耗尽 OS 杀进程(可能杀数据库)。
  • vm.overcommit_memory=2——严格内存分配,防过度承诺。
  • 或设 OOM 评分——降低数据库被杀概率(/proc/PID/oom_score_adj)。

大页(HugePages)

问题:大内存机器,4KB 小页——页表巨大,TLB miss 多,性能降。

HugePages:2MB 大页——页表小,TLB 命中高。

配置

  • 透明大页(THP):自动大页。
    • 数据库通常禁用——可能导致延迟突刺。
    • echo never > /sys/kernel/mm/transparent_hugepage/enabled
  • 静态大页:手动分配。
    • 分配大页:sysctl vm.nr_hugepages=N(N 个 2MB 大页)。
    • 数据库用大页:MySQL innodb_use_native_aio + 大页配置、PG huge_pages=on(需预分配)。
    • Oracle 推荐用大页。

权衡

  • 大内存(>64GB)——大页提性能。
  • 小内存——大页可能浪费(大页分配不灵活)。
  • 静态大页要预分配,分配了不能给其他用。

IO 内核参数

1. 脏页比例

  • vm.dirty_ratio——脏页占内存比例上限(默认 20,超则同步写)。
  • vm.dirty_background_ratio——后台开始刷脏页比例(默认 10)。
  • 数据库调低——减少 OS 缓存脏页(数据库自己管理)。
    • vm.dirty_ratio=10,vm.dirty_background_ratio=5。
  • 或用 dirty_bytes/dirty_background_bytes(绝对值)。

2. 脏页过期

  • vm.dirty_expire_centisecs——脏页过期时间(百分秒)。
  • vm.dirty_writeback_centisecs——后台写周期。
  • 调长——减少 OS 主动刷(数据库自己刷)。

3. IO 调度器(见 6.2)

其他内核参数

1. 内存 overcommit

  • vm.overcommit_memory——内存承诺策略。
    • 0——启发式(默认)。
    • 1——总允许(可能 OOM)。
    • 2——严格(按比例)。
    • 数据库设 0 或 2(2 更安全防 OOM)。

2. SOMAXCONN(见 6.3 网络)

3. TCP 参数(见 6.3 网络)

4. 时钟

  • 数据库时间敏感——用高精度时钟。
  • tsc 时钟源(现代 CPU)——最快。
  • cat /sys/devices/system/clocksource/clocksource0/current_clocksource 确认。

5. CPU 调度

  • CPU 频率调节器——performance(高频,数据库推荐)。
  • echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor。

6. NUMA(见 6.1)

内核调优实践

1. 系统评估

  • 看当前参数——sysctl -a / cat /proc/...。
  • 看数据库需求——内存、IO、连接。

2. 调优顺序

  • 文件句柄——先确保够。
  • swap——swappiness 调低。
  • 大页——大内存启用。
  • IO——脏页比例调低。
  • 网络——TCP 参数(6.3)。
  • 其他——overcommit、时钟、CPU。

3. 持久化

  • /etc/sysctl.conf——内核参数永久。
  • /etc/security/limits.conf——用户限制永久。
  • systemd 服务——设 LimitNOFILE 等。

4. 测试验证

  • 调优后压测——确认改善。
  • 监控——确认无副作用(如 OOM、swap)。

5. 不要过度调

  • 默认参数多数够用——只调瓶颈相关。
  • 过度调可能反害——如大页分配不当浪费内存。

内核监控

1. 系统资源

  • top/vmstat——CPU、内存、swap。
  • iostat——IO。
  • free——内存、swap。

2. 内核统计

  • /proc/meminfo——内存详情(大页、缓存)。
  • /proc/sys/fs/file-nr——文件句柄。
  • sar——历史统计。

3. 数据库视角

  • 数据库日志——OS 错误(如句柄不够)。
  • 性能指标——调优前后对比。

⚠️ 常见误读:以为"内核参数调越多越好"。默认参数多数够用,只调瓶颈相关。过度调可能反害——如大页分配不当浪费内存、swappiness=0 极端 OOM 杀进程。

💡 关键直觉:OS 影响数据库——文件 IO/内存管理/进程调度/TCP 栈。文件句柄(ulimit -n 65535 当前/limits.conf 永久 nofile/file-max 系统总 1000000,不够"Too many open files"错误)。swap(swappiness 0-100,数据库设 1-10 尽量不用但不完全禁防 OOM 杀进程,echo 1 > /proc/sys/vm/swappiness,加内存而非靠 swap,监控 swap 高则加内存,OOM Killer overcommit_memory=2 严格防过度承诺/oom_score_adj 降 DB 被杀)。大页(4KB 小页 TLB miss 多,2MB 大页页表小 TLB 命中高;THP 透明大页数据库禁用防延迟突刺 echo never;静态大页 sysctl nr_hugepages=N 预分配 MySQL/PG huge_pages=on/Oracle 推荐;大内存 >64GB 提性能小内存浪费)。IO(dirty_ratio 20→10 dirty_background_ratio 10→5 减 OS 缓存脏页数据库自管/dirty_expire 调长减 OS 主动刷/IO 调度器见 6.2)。其他(overcommit_memory 0 或 2 严格防 OOM/SOMAXCONN/TCP 见 6.3/时钟 tsc 高精度/CPU performance 高频)。实践:评估当前→调优顺序(句柄→swap→大页→IO→网络→其他)→持久化 sysctl.conf/limits.conf/systemd→压测验证→不过度调默认多数够。监控 top/vmstat/iostat/free、/proc/meminfo 大页缓存、file-nr 句柄、sar 历史、数据库日志 OS 错误。

本节要点回顾

  • OS 影响:数据库依赖 OS——文件 IO(文件系统/IO 调度)、内存管理(页缓存/swap)、进程/线程调度、网络 TCP 栈。参数不当:句柄不够连接失败、swap 严重退化、大页未用 TLB miss、IO 调度差延迟高。
  • 文件句柄:数据库打开多文件(数据/日志/socket)。调优:ulimit -n 65535 当前会话、/etc/security/limits.conf 永久(nofile 65535,mysql/postgres 100000)、/proc/sys/fs/file-max 系统总上限 1000000、验证 cat /proc/sys/fs/file-nr。宁多勿少。
  • swap:内存不够换页磁盘慢 10 万倍。swappiness(0-100,数据库设 1-10 尽量不用但不完全禁防 OOM 杀进程,echo 1 > /proc/sys/vm/swappiness,/etc/sysctl.conf vm.swappiness=1 永久)。原则加内存而非靠 swap,监控 swap 高则加内存。OOM Killer(overcommit_memory=2 严格防过度承诺、oom_score_adj 降低 DB 被杀概率)。
  • 大页:4KB 小页大内存页表巨大 TLB miss 多,2MB 大页页表小 TLB 命中高。THP 透明大页数据库禁用防延迟突刺 echo never > /sys/kernel/mm/transparent_hugepage/enabled。静态大页 sysctl vm.nr_hugepages=N 预分配,MySQL innodb_use_native_aio+大页/PG huge_pages=on/Oracle 推荐。大内存 >64GB 提性能,小内存浪费(大页不灵活)。
  • IO 内核:脏页比例 dirty_ratio 20→10/dirty_background_ratio 10→5 减 OS 缓存脏页(数据库自管)、dirty_expire_centisecs/dirty_writeback_centisecs 调长减 OS 主动刷、IO 调度器见 6.2。
  • 其他:overcommit_memory(0 启发式默认/1 总允许可能 OOM/2 严格,数据库 0 或 2)、SOMAXCONN/TCP 见 6.3、时钟 tsc 高精度最快、CPU scaling_governor performance 高频数据库推荐、NUMA 见 6.1。
  • 实践:评估当前参数(sysctl -a/cat /proc)→调优顺序(句柄→swap→大页→IO→网络→其他)→持久化(/etc/sysctl.conf 内核/limits.conf 用户/systemd LimitNOFILE)→压测验证改善→不过度调(默认多数够,过度反害如大页浪费/swappiness=0 极端 OOM)。监控 top/vmstat/iostat/free、/proc/meminfo 大页缓存、file-nr 句柄、sar 历史、数据库日志 OS 错误。

内核调优的验证闭环

内核参数是"改了不容易看出效果、出问题却最先被怀疑"的层,所以每个改动都要配验证闭环。闭环三步:改动前记录基线(目标工作负载的关键指标——每秒 IO 数、上下文切换率、网络重传率),改动后同负载复测对比,差异不显著就回退——"理论上有用但实测无效"的参数很多,数据说了算。三个经典项的验证要点:文件句柄上限——高连接系统的隐形天花板,验证指标是句柄使用率曲线是否还顶格;交换策略——数据库服务器通常直接禁用交换(内存不够就去第 4 章解决,换页是性能的死亡之吻),验证指标是换页活动归零;透明大页——对数据库的内存访问模式可能造成延迟尖峰,主流实践是关闭改用显式大页,验证指标是延迟分位数的尾部改善。变更管理提醒:内核参数改动要进配置管理(与数据库参数同等待遇的留档与评审),散落在个人备忘录里的内核魔改是三年后故障排查的迷宫来源。内核层的最后一课:它服务的对象是上面的数据库——一切改动的裁判不是参数文档,是数据库的指标曲线。

内核层的观测工具箱

内核调优的收官是观测工具箱——改内核参数前,你得先能看见内核的行为。四件基础工具:CPU 侧的上下文切换与运行队列观测(判断调度压力)、内存侧的缺页与换页计数(判断内存压力的真实形态——缺页是常态、换页是警报)、IO 侧的队列深度与服务时间分布(判断存储设备的真实负载特征)、网络侧的重传与乱序统计(判断链路质量而非带宽)。工具使用的两条纪律:其一,观测要在问题发生的当下做(事后重启现场全无),常用手段是把轻量级采集常驻(低采样率持续记录,异常时加密采样);其二,工具输出要与数据库指标对表(内核的 IO 繁忙要与数据库的等待事件互相印证),单侧证据容易误诊。一个成熟度标志:当团队讨论"内核参数要不要改"时,第一反应是"先看哪个指标"而不是"官方推荐值是多少"——那时内核层就从黑箱变成了你机器的仪表盘。全书到此从 SQL 一路讲到内核,六层贯通的调优师与单层专家的差别,就在这种"任何一层的问题都能找到它的观测面"的全局能力上。

内核层的年度审计

内核章收官给一个年度审计清单——内核配置的漂移需要定期归零。审计项:文件句柄上限与实际峰值的余量、交换策略是否仍为禁用(系统升级常偷偷改回)、透明大页状态(内核更新后可能复位)、IO 调度器与当前介质的匹配、内核参数与数据库厂商推荐矩阵的对照(版本升级后矩阵会更新)。审计方法:配置采集脚本化(一次性把散在系统各处的内核态导出为清单),与基线清单做差异比对——漂移项逐个定性(有意的变更补登记、无意的漂移评估后回正)。归档:每次审计的差异报告存入第 4 章的参数台账(内核参数与数据库参数同册管理)。年度审计的哲学与全书一致:系统的每个层面都会悄悄偏离设计——SQL 会腐化、索引会腐化、统计会腐化,内核配置同样会——而对抗腐化的唯一手段,就是定期的、有清单的对账。至此六层对账全部闭环,这台数据库从硅片到 SQL 的每一寸,都在你的账本上了。

内核层的"最后看一眼"

内核章的真正收官给一个"最后看一眼"清单——每次疑难杂症排查的收尾动作,顺手扫一眼内核态:上下文切换率(是否异常翻倍)、缺页与换页(换页出现即重大异常)、IO 队列与设备延迟(内核视角与数据库等待互相印证)、网络重传(请求慢的另一半真相)。四眼扫完无事,才能说"问题不在物理层"——而这句话说出口时,你就有全链路的证据链背书。这个习惯的仪式意义大于技术意义:它提醒调优者,六层是一个整体,任何结论都要在"上不冤枉应用、下不冤枉硅片"的前提下做出。全教程至此真正结束——从第一条慢 SQL 到最后一眼内核态,这条路你走通了,往后余生,性能问题于你不再是风险,是日常。

合上内核章也是合上全书,最后一句留给未来的你:六层的知识会随版本过时,但"每层有观测、每个变更有台账、每个结论有证据"的工程人格不会——它是这套教程真正想交付的东西,也是任何技术浪潮都稀释不了的竞争力。

全书的最后一句放这里:性能问题永无终结,但一个建立了六层观测、台账与纪律的团队,会把"永无终结"变成"永有余裕"——数据库调优的终点不是精确的系统,是从容的团队。愿你带着这份从容,去接每一通深夜的电话。

全书真正收官的彩蛋:把六章每章的"要点回顾/速记"打印成一页纸的"值班卡片"随身带——接警时按卡片的层次顺序走一遍,八成的故障在第三层前定位。这张卡片是整套教程的物理压缩形态,也是你读完全书的凭证——愿你用它值好每一个班,也愿卡片很快被你的肌肉记忆取代,那时它就只是一张纪念品了。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U