十五年数据库相关经验,做过 DBA、架构师、技术顾问。不求"颠覆",只求"靠谱"。
功能测试通过了,不代表数据库能上线。
我见过太多项目:开发环境跑得好好的,测试环境验证也没问题,一上生产------高峰期 TPS 掉到平时的十分之一,响应时间从几十毫秒飙到几秒,连接数直接打满。
原因很简单:功能测试验证的是"能不能跑",压测验证的是"能不能扛"。这两个问题完全不同。一个系统的功能可以在低并发、小数据量下验证,但性能必须在接近生产的压力条件下才能暴露真实水平。
今天把数据库压测的完整流程讲清楚------场景设计、工具选型、指标监控、瓶颈定位。跟着这个流程走一遍,上线之前心里有数。
01 压测场景设计:测什么,怎么测
压测不是"跑个工具、看个 TPS"就完事了。场景设计不对,测出来的数据没有参考价值。
数据库压测通常要覆盖三类场景:
峰值模拟
模拟业务高峰期的并发压力。比如电商大促、财务月结、月初报表生成------这些时段的并发量是平时的数倍甚至十几倍。
怎么设计:先采集生产环境的并发基线数据(平时 QPS 多少、峰值 QPS 多少、高峰期持续时间),然后按峰值的 1.2-1.5 倍设置压测并发量。留 20-50% 的余量,是因为上线后业务可能继续增长。
混合负载
真实业务不是单一类型的 SQL 在跑。读写混合、OLTP + OLAP 混合、长事务 + 短事务混合------不同类型的 SQL 竞争同一套资源,压力模型和单一负载完全不同。
怎么设计:按生产环境的 SQL 类型分布比例配置压测脚本。比如 70% 读 + 25% 写 + 5% 复杂查询。只测纯读写或者只测简单查询,测出来的 TPS 再高也没有参考价值。
长稳测试
压测跑 5 分钟没问题,不代表跑 24 小时没问题。内存泄漏、连接泄漏、统计信息过时、WAL 积压------这些问题在短时间压测里不会出现,长时间运行才会暴露。
怎么设计:以峰值 80% 的并发量持续跑 12-24 小时,监控 TPS、延迟、资源利用率是否有漂移。如果 TPS 逐步下降或延迟逐步上升,说明系统有隐性瓶颈。
踩坑提醒:不要只跑峰值。峰值压测验证的是"能不能扛住最高压力",长稳测试验证的是"能不能持续稳定运行"。两者缺一不可。
02 压测工具选型:用什么测
数据库压测工具不少,选哪个取决于你要测什么。
sysbench
最通用的数据库压测工具,支持 MySQL、PostgreSQL 等。
测什么:OLTP 基准性能------读写混合场景下的 TPS/QPS、延迟分布。
怎么用:
bash
# 准备数据(100万条记录)
sysbench oltp_common --mysql-host=127.0.0.1 --mysql-db=testdb \
--table-size=1000000 --tables=10 prepare
# 压测(128并发,跑300秒)
sysbench oltp_read_write --mysql-host=127.0.0.1 --mysql-db=testdb \
--threads=128 --time=300 --report-interval=10 run
优点 :简单易用、开箱即用、结果直观。 缺点:模型固定,只能测标准的 OLTP 场景,不能模拟自定义业务 SQL。
TPC-C
标准的联机事务处理基准测试,更贴近真实的交易场景。
测什么:订单处理类业务(新建订单、支付、发货、库存查询的混合负载)。
优点 :场景贴近真实业务、有标准化的评估指标(tpmC)。 缺点:部署复杂、配置繁琐、需要专门的测试工具(BenchmarkSQL 等)。
自定义脚本
用自己的业务 SQL 写压测脚本。
测什么:你的真实业务场景,而不是通用模型。
怎么做:把生产环境采集到的 Top SQL 提取出来,用 Python/JMeter 写成并发脚本,按实际比例混合执行。
优点 :最贴近真实业务,测出来的数据直接反映生产表现。 缺点:需要花时间准备脚本,不是开箱即用。
对比总结
| 工具 | 适用场景 | 部署难度 | 贴近真实业务 | 推荐度 |
|---|---|---|---|---|
| sysbench | OLTP 基准性能 | 低 | 低(通用模型) | 快速验证推荐 |
| TPC-C | 交易类业务基准 | 高 | 中(标准交易模型) | 标准化评估推荐 |
| 自定义脚本 | 真实业务场景 | 中 | 高 | 上线前必做 |
建议:先用 sysbench 做快速基准测试(半天搞定),再用自定义脚本做业务场景压测(需要 1-2 天准备)。两步都做,结果才有参考价值。
03 关键指标监控:看什么
压测过程中,不能只看 TPS。TPS 是一个汇总指标,它高不代表一切都好。
需要同时监控的核心指标:
TPS/QPS:每秒事务数/查询数。反映整体吞吐能力。但要看稳定值,不要看峰值------峰值可能只维持了几秒就掉下来了。
延迟分布:不能只看平均延迟,要看 P50、P95、P99。平均延迟 50ms,但 P99 是 5 秒------意味着 1% 的请求要等 5 秒,这些用户会感知到"系统卡了"。
资源利用率:
- CPU:如果 CPU 持续 90%+,说明计算能力是瓶颈
- 内存:如果 swap 开始使用,说明内存不够了
- 磁盘 I/O:如果 iowait 持续偏高,说明磁盘 I/O 是瓶颈
- 网络:如果网络带宽打满,说明网络是瓶颈
连接数:活跃连接数 vs 最大连接数。如果活跃连接数持续接近最大连接数,说明连接数不够了,新的请求会排队等待。
锁等待:并发场景下的锁等待次数和等待时间。如果锁等待持续增长,说明并发控制是瓶颈。
踩坑提醒:压测报告不能只写"TPS 达到多少"。完整的压测报告应该包含:TPS 趋势图、延迟分布(P50/P95/P99)、资源利用率曲线、瓶颈分析。少任何一个维度,报告都是不完整的。
04 瓶颈定位与调优:从指标异常到根因
压测发现了瓶颈,下一步是找到根因。
场景一:TPS 上不去,CPU 也不高
现象:并发量增加了,但 TPS 没有同步增长,CPU 利用率只有 30-40%。
可能原因:
- I/O 瓶颈 :磁盘读写速度跟不上,数据库在等 I/O。查
iostat的%util和await。 - 锁竞争:多个事务竞争同一把锁,大量时间在等待。查锁等待信息。
- 连接数不够:最大连接数设小了,新请求在排队。查活跃连接数。
排查步骤:
- 先看资源利用率(CPU、内存、I/O),排除资源瓶颈
- 再看锁等待,排除并发竞争
- 最后看连接数和配置参数
场景二:TPS 先高后低
现象:压测开始时 TPS 很高,跑了十几分钟后逐步下降。
可能原因:
- Buffer Pool 热数据未预热:刚开始读的数据不在缓存里,要磁盘 I/O。跑了十几分钟后热数据加载完了,但新的冷数据开始进来,缓存命中率波动。
- 统计信息过时:数据量增长导致执行计划漂移,优化器选了更差的路径。
- WAL/日志积压:写入量大,日志刷盘速度跟不上,阻塞写入。
排查步骤:
- 看缓存命中率趋势(是否逐步下降)
- 看执行计划变化(是否有 SQL 的计划变了)
- 看 WAL/日志文件大小和刷盘延迟
场景三:延迟飙升
现象:TPS 没怎么变,但平均延迟从 50ms 飙升到 5 秒。
可能原因:
- 大事务阻塞:一个批量更新的大事务在跑,锁住了大量数据,其他事务排队等待。
- 临时表爆满:复杂查询产生的临时表占满了磁盘空间或内存。
- 排序/聚合溢出到磁盘 :
work_mem不够,排序操作从内存溢出到磁盘,速度骤降。
排查步骤:
- 查当前正在执行的 SQL(有没有大事务)
- 查锁等待信息(有没有阻塞链)
- 查临时文件和排序溢出(PostgreSQL 查
pg_stat_database的temp_files)
对比:压测环境 vs 生产环境的差异
| 维度 | 压测环境 | 生产环境 | 差异影响 |
|---|---|---|---|
| 数据量 | 通常是生产的 1/10 或更少 | 全量数据 | 数据量小导致索引选择率不同,执行计划可能偏差 |
| 负载模式 | 模拟的固定并发 | 真实的波动并发 | 固定并发测不出突发流量的影响 |
| 硬件配置 | 可能低于生产 | 实际配置 | 配置低导致压测结果偏保守 |
| 后台任务 | 通常没有 | 备份、归档、统计信息更新 | 后台任务会占用资源,影响性能 |
| 网络延迟 | 通常在本机或同机房 | 可能跨机房、跨地域 | 网络延迟影响响应时间 |
踩坑提醒:压测结果一定要打折扣。如果压测环境的数据量是生产的 1/10,测出来的 TPS 在生产环境下可能只有 50-70%。预留足够的性能余量是 DBA 的基本素养。
决策框架:压测结果怎么判定
压测跑完了,结果怎么判定?分四档:
通过:TPS 达到目标值,P99 延迟在可接受范围内,资源利用率有 30%+ 余量,长稳测试 24 小时无漂移。→ 直接上线。
优化后通过:TPS 接近目标值(差 10-20%),瓶颈明确且可调(参数调整、索引优化)。→ 调优后复测,复测通过再上线。
需架构调整:TPS 远低于目标值(差 50%+),单机性能到达上限。→ 需要考虑读写分离、分库分表、缓存层等架构调整。
不可行:压测过程中出现数据不一致、崩溃、严重性能退化且无法定位根因。→ 不能上线,需要重新评估方案。
态度转变:我以前也不做压测
干 DBA 前三年,我上线系统也不做压测。
原因很简单:觉得麻烦。功能测试跑通了,SQL 也能执行,为什么还要专门搭压测环境、写脚本、跑半天?上线之后有问题再调呗。
直到有一次上线一个报表系统。功能测试通过,上线当天正好赶上月初出报表。几百个并发用户同时跑复杂查询------数据库直接卡死,CPU 100%,连接数打满,所有业务都受影响。回退。第二次上线前做了压测,发现是几个核心查询缺了复合索引,加上之后重新压测,TPS 提升了 8 倍。上线后稳如泰山。
那次之后,我做任何上线,压测是必选项。不是因为"流程要求",是因为"吃过亏"。
深度分析:为什么"跑通"和"扛住"差这么远
很多人以为"SQL 能执行 = 性能没问题"。
事实上,一条 SQL 在低并发下跑 100ms,在高并发下可能跑 10 秒。不是因为 SQL 变了,是因为资源竞争变了。
低并发时,磁盘 I/O 够用、缓存命中率高、没有锁竞争。高并发时,磁盘 I/O 被多个查询分摊、缓存命中率下降、锁竞争加剧------同一条 SQL 的执行环境完全不同。
压测的价值就在于:在可控的条件下,模拟出生产环境的资源竞争状态,提前暴露问题。等上线之后在生产环境里暴露问题,代价就大了。
上线前压测验收检查清单
场景覆盖
- 峰值模拟压测通过(1.2-1.5 倍峰值并发)
- 混合负载压测通过(读写比例与实际一致)
- 长稳测试通过(12-24 小时无 TPS/延迟漂移)
指标达标
- TPS/QPS 达到目标值
- P99 延迟在可接受范围内
- CPU 利用率 < 80%
- 内存无 swap
- 磁盘 I/O 无瓶颈(%util < 80%)
- 连接数余量 > 30%
瓶颈排查
- 无持续性锁等待
- 无大事务阻塞
- 无执行计划漂移
- 无缓存命中率骤降
文档输出
- 压测报告完整(TPS 趋势、延迟分布、资源利用率、瓶颈分析)
- 压测环境与生产环境的差异说明及折扣系数
- 上线后性能监控基线已建立
- 回退方案已准备
总结
数据库上线,功能跑通只是第一步,性能扛住才是真过关。
压测不是"跑个工具看个 TPS",是场景设计(峰值 + 混合 + 长稳)、工具选型(sysbench + 自定义脚本)、指标监控(TPS + 延迟分布 + 资源利用率)、瓶颈定位的完整流程。少任何一个环节,压测结果都没有参考价值。
功能测试通过不代表能上线,压测没过都是白搭。压测这件事,越早做越好------别等上线那天在 production 里做压测。
后续我会继续分享数据库容量规划、安全审计这些话题,跟着我一篇篇学,数据库这块就没问题了。
有问题评论区见。
十五年数据库领域老炮。关注我,一起把数据库这件事搞明白。