1. 压测到底是干什么的:它解决的三个真实问题
先说个我早年踩过的坑。那时候公司有个核心交易系统,上线前功能测试跑了整整两周,所有用例全绿,结果上线当天晚高峰直接卡死,数据库连接池被打满,接口响应时间从 20 毫秒飙到 12 秒,最后只能紧急回滚。复盘的时候查监控,发现数据库的活跃连接数早就到了 800 的上限,而功能测试阶段我们最多只模拟了三五十个并发用户。
这件事给我上了一课:功能测试验证的是"系统能不能正确完成操作",而压力测试验证的是"系统在预期负载和超预期负载下还能不能正确完成操作"。前者解决对错问题,后者解决存活问题。数据库作为整个应用链路的最终落点,几乎所有的业务请求最终都要打到它头上,一旦它先垮掉,上游的服务再快也是白搭。
数据库压力测试,简单说就是通过工具模拟大量并发请求,把数据库置于真实的、甚至超过真实的负载之下,观察它的吞吐量、响应时间、资源消耗、稳定性,进而回答三个问题:
- 系统能撑住多大的并发量。这是最直接的产出,比如"单库 2000 QPS 下平均响应时间 30ms,8000 QPS 下平均响应时间 850ms 且开始出现明显排队"。
- 瓶颈到底在哪里。是 CPU 先被吃满,还是磁盘 IO 先到极限,还是连接数不够用,还是 SQL 本身写得差。只有压测才能把这类问题逼到明面上。
- 什么时候会崩、崩了会怎样。在超过极限负载的三到五倍下持续压测,看连接池是否被耗尽、磁盘空间是否被撑爆、锁等待是否导致大面积超时,为限流、降级、扩容提供数据依据。
所以压测这个事的定位,不是"上线前的锦上添花",而是"上线后能不能睡得着觉"的底线工程。它也不只是 DBA 的事,开发、架构、运维都必须参与进来:开发负责根据压测结果优化 SQL 和表结构,架构负责判断分库分表还是加缓存,运维负责调整数据库参数和操作系统层配置。
适合读这篇文章的人,我理解有三类:第一类是刚接手数据库维护的开发或运维,想系统搞懂压测该怎么做;第二类是团队里没有专职 DBA、需要自己扛起性能验证的后端工程师;第三类是准备做技术方案汇报的人,看完可以直接照着一套完整流程落地,产出的报告也能对上领导的胃口。
2. 动手之前先想清楚的四件事,比工具重要得多
我见过太多人一上来就装 JMeter、写压测脚本,压完一脸懵——数据出来了,但不知道这数据意味着什么。压测最忌讳的就是"先跑起来再说"。真正有经验的做法,是在执行压测之前把下面四个问题彻底理清。
2.1 这次压测的目标是什么
目标决定了你的测试设计和指标选取。你要先定义清楚"什么样算通过"。常见的目标类型有这么几种:
| 目标类型 | 典型表述 | 核心指标 |
|---|---|---|
| 容量验证 | 支撑 5000 并发在线用户 | 并发连接数、QPS |
| 性能达标 | 核心接口 TP99 小于 300ms | TP50、TP95、TP99 |
| 稳定性验证 | 持续压测 8 小时无内存泄漏 | 内存曲线、连接数曲线 |
| 极限摸底 | 找出系统能承受的最大负载 | 拐点 QPS、资源利用率 |
| 调优验证 | 对比参数调优前后的性能差异 | CPU、IO、响应时间 |
很多团队把"压测"本身就当成目标,一键跑完几十万请求,然后报告上写"系统稳定运行,无明显异常"。这种报告价值几乎为零,因为你没有给出"这么多请求意味着什么样的业务量级"的换算逻辑。比如 10 万 QPS 对一个双十一大促可能都不够看,但对一个只有 2 万日活的小系统已经是碾压级的负载,所以目标数字一定是从业务推导出来的,而不是拍脑袋定的。
2.2 你有没有拿到真实的业务基线
设计压测最容易被忽视、其实最关键的一步,是弄清楚生产环境当前的真实负载情况。我通常建议先去生产库拉一周的监控数据,重点看四样东西:每日 PV/UV 对应的数据库 QPS 峰值、连接数峰值、慢查询数量、资源利用率高峰时段。有了这些基线数据,你才能算出"未来半年业务增长 3 倍后需要压到多少的 QPS",也才能合理设计压测的比例模型。
举个具体例子。某个电商系统,日常高峰 QPS 是 1500,其中商品查询占 70%、订单创建占 15%、购物车操作占 10%、支付回调占 5%。那么大促压测就应该按这个比例放大到 4500 或者 7500 QPS,而不是均匀地压五种接口。均匀分布压出来的结果在生产环境下毫无参考意义——因为真实的流量从不均匀。
2.3 压测环境能不能"基本等同"生产
数据库压测有个很尴尬的现实:性能表现对环境和数据极其敏感。你在测试环境压出来的 2000 QPS,和生产环境的 2000 QPS 可能完全是两个数量级。影响因素包括:
- 硬件差异:CPU 核数、磁盘类型(SSD 还是机械盘)、内存大小,直接决定了数据库的极限能力。
- 数据量差异:测试库里 100 万行数据和生产库 2 亿行数据,同一个 SQL 的执行计划可能天差地别——索引失效、全表扫描、排序落盘这些坑,在小数据量下根本不会暴露。
- 配置差异:MySQL 的
innodb_buffer_pool_size、max_connections,Oracle 的SGA/PGA大小,配置不同,压测结果可以差出好几倍。
所以我的建议是:如果预算允许,单独搭一套和生产同规格的压测环境;如果不行,至少要保证数据量级接近。最务实的做法是从生产库克隆一份脱敏数据到压测库,行数尽量保持在一个数量级内。用一个小到连索引都走不动的测试库压出来的数据,除了安慰自己,没有任何工程价值。
2.4 谁来盯、怎么盯、出问题了怎么办
压测不是把脚本一放就撒手不管。你要提前定好:谁负责盯数据库监控大盘,谁负责盯压测工具端的报错日志,谁负责在数据库负载异常飙升时紧急停止压测。一般我会在服务端准备一套应急方案,包括:sudo systemctl stop压测脚本对应的应用服务、手动kill掉查询线程、必要时直接断开压测工具的网络出口。这些事情看起来不起眼,但在高峰期压测时,晚十秒止损和早十秒止损的差别,可能就是一次生产事故和一次成功演练的差别。
3. 工具选型的底层逻辑:不是越流行越好
聊到数据库压测工具,圈子里常用的就那么几类:JMeter、sysbench、pgbench(PostgreSQL 自带)、HammerDB,以及自己写脚本直连数据库压测。很多人纠结选哪个,其实选型的底层逻辑不是"哪个更火",而是"你的压测场景需要工具提供到哪一层的能力"。
3.1 JMeter:适合业务接口层的全链路压测
JMeter 大概是国内团队用的最多的压测工具,它的定位是协议层压测工具,可以模拟 HTTP 请求,也可以通过 JDBC 驱动直连数据库发送 SQL。它能做数据库压测,但更擅长的其实是"从业务接口到数据库的完整链路压测"——用户通过 API 网关访问后端服务,后端服务再通过连接池访问数据库。这种压测方式最接近真实生产环境,因为你在压数据库的同时,等于也顺带验证了 Web 服务器的并发能力和连接池的配置是否合理。
JMeter 做数据库压测的关键配置,我后面会详细讲。这里先说选型结论:如果你的目标是验证"整个业务链路在真实负载下的表现",JMeter 是首选。通用性强、上手快、报告可读性好、团队协作方便,这些优点让它成为性能测试团队的主流选择。
3.2 sysbench 与 pgbench:适合数据库内核性能摸底
如果你的目标不是业务链路,而是想测试数据库本身在单位时间能处理多少事务,那我更推荐 sysbench。它的特点是轻量、纯粹:不经过应用服务器,直接用多线程模拟事务请求打到数据库上。它内置了oltp_read_write、oltp_point_select、oltp_insert等多种测试模型,可以很方便地对 MySQL、PostgreSQL 做内核级的基准测试。
sysbench 最大的优点是结果非常稳定且可复现,适合用来做硬件换代后的性能对比、数据库版本升级前后的性能对比、参数调优前后的对比。比如你要判断"从 MySQL 5.7 升到 8.0 到底快了多少",用 sysbench 在同一台机器上跑同样的 workload,数据一出来高下立判。它的缺点是——它只测数据库本身,不关心你的业务 SQL 写得多烂。所以它不能替代业务压测,只能作为底层能力的参考。
3.3 自研压测脚本:处理复杂业务场景的最后方案
我遇到过一个场景:业务的写入逻辑非常复杂,一条数据要同时更新主表、写入流水表、刷新缓存,并且依赖 Redis 里的分布式锁。这种跨组件且有先后依赖的流程,JMeter 要配置复杂的后置处理器和断言才能模拟,而自研一个 Python 脚本,直接用连接池发 SQL,配合 Redis 客户端模拟锁竞争,反而更灵活、更容易控制节奏。
自研脚本一般在两种情况下选:一是现有工具无法表达你的业务模型,二是你需要精确控制请求的到达时间分布(比如模拟突发峰值还是平滑爬坡)。但自研脚本要特别注意一个坑:用单线程脚本驱动不了足够的并发。很多人用 Python 写脚本,只开了几十个线程,压了半天数据库端的连接数根本没上去,结果压了个寂寞。正确的做法是用asyncio配合连接池(比如asyncpg),或者直接用gevent协程,单机就能模拟上千并发。
实际做选型时,我一般用"场景三问"来做决策:压的是数据库内核还是业务链路?如果是前者,优先 sysbench;需要复现生产流量特征吗?如果需要,JMeter 更合适;现有工具搞不定业务模型吗?那再考虑自研。这三个问题问完,选型基本不会有大的偏差。
4. 从准备到报告:一次完整压测的执行过程
理论聊完,下面给一套从前到后可以直接照着做的完整流程。这个过程我跑过无数次,任何环境都适用,核心思路是一致的。
4.1 准备压测数据:不要用小表骗自己
先建一个独立的测试库,不要污染业务库。然后准备数据,数据量以生产环境的行数为基准,起码做到 80% 以上的量级。用存储过程或者脚本灌数据是常见做法,比如 MySQL 里可以用这样的方式快速生成测试数据:
-- 创建一张订单表 CREATE TABLE `test_orders` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL, `amount` DECIMAL(10,2) NOT NULL, `status` TINYINT NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL, PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 插入测试数据 INSERT INTO test_orders (user_id, amount, status, created_at) SELECT FLOOR(RAND() * 1000000), ROUND(RAND() * 1000, 2), FLOOR(RAND() * 5), DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 365) DAY) FROM information_schema.columns LIMIT 1000000;用一条INSERT ... SELECT语句从信息表里重复取数据,可以快速生成百万行级别的测试数据。但如果你要生成上亿行,建议用存储过程循环插入,并且分批提交,不然一次大事务会把 undo log 撑爆。
4.2 JMeter 配置数据库压测的关键步骤
用 JMeter 做数据库压测,很多人卡在 JDBC 配置上,我先说最容易出错的几个点。首先要下载对应数据库的 JDBC 驱动包(MySQL 用mysql-connector-j,PostgreSQL 用postgresql),放到 JMeter 的lib/ext目录下。然后在测试计划里添加JDBC Connection Configuration:
- Database URL 的写法是
jdbc:mysql://压测机IP:3306/testdb?useSSL=false&allowPublicKeyRetrieval=true,其中allowPublicKeyRetrieval=true这个参数不能丢,否则新版 MySQL 驱动会报公钥检索错误。 - JDBC Driver Class 填
com.mysql.cj.jdbc.Driver。 - Username / Password 填压测库的专用账号。
- Max Pool Size(最大连接数)和
Max Waits(等待超时毫秒数)这两项是压测的核心参数。Max Pool Size 建议设置成 50,它会成为你压测并发的一个上限——如果你设得太小,比如 5,那么即使你在线程组配了 500 个并发用户,实际打到数据库上的连接也只有 5 个,压出来的结果毫无意义。
然后配置JDBC Request,在 SQL Query 里写要压测的 SQL。这里有个技巧:压测时要针对性地压不同的 SQL,不要只压一条。我一般会按业务比例建多个 JDBC Request,分别压查询类 SQL、写入类 SQL、更新类 SQL,然后用Throughput Controller或Switch Controller控制它们的占比。比如商品查询占 60%,订单创建占 25%,状态更新占 15%,这样压出来的整体效果才贴近真实。
线程组配置上,建议用"阶梯式"压测,不要直接拉满。比如:线程数从 100 开始,每 5 分钟增加 100,直到增加到 1000。这样做的目的,是为了观察数据库在不同负载阶段的表现曲线,方便找到性能拐点。如果一开始就压 1000 并发,你只能知道"它挂了",而不知道"从哪个并发开始性能开始劣化"。
4.3 选择压测的 SQL:必须来自生产慢日志
这一步很关键,但也是最容易被省略的一步。压测的 SQL 不应该由你"临时想"几条,而应该来自生产环境的slow_query_log和performance_schema统计。方法很简单:上线前把生产库的慢查询日志开一段时间,把执行频率高、单次执行时间超过 50ms 的 SQL 全部捞出来,这些才是你真正需要压的 SQL。
我自己每次做压测前,都会先从生产库里捞出 TOP 20 高频 SQL,按照执行频次加权整理成一个压测集合。为什么要这么做?因为压测的本质是"制造真实的负载",而真实的负载就是那些在生产环境高频执行的 SQL。如果你自己随便写几条简单的SELECT去压,测出来的数据是"数据库在上简单负载时的表现",距离"数据库在上业务真实负载时的表现"差得很远。
4.4 直连压测底座的 sysbench 用法
如果你需要的是数据库底座的性能数据,sysbench 的用法也不复杂。以 MySQL 为例,先用prepare阶段生成一张压力测试表:
sysbench /usr/share/sysbench/oltp_read_write.lua \ --mysql-host=127.0.0.1 \ --mysql-port=3306 \ --mysql-user=root \ --mysql-password=yourpassword \ --mysql-db=sbtest \ --tables=10 \ --table-size=10000000 \ --threads=16 \ prepare注意--tables=10和--table-size=10000000决定了测试表的总行数,--threads是压测客户端的并发线程数。prepare阶段结束后,执行run阶段:
sysbench /usr/share/sysbench/oltp_read_write.lua \ --mysql-host=127.0.0.1 \ --mysql-port=3306 \ --mysql-user=root \ --mysql-password=yourpassword \ --mysql-db=sbtest \ --tables=10 \ --table-size=10000000 \ --threads=128 \ --time=300 \ --report-interval=5 \ run--time=300表示压测 300 秒,--report-interval=5表示每 5 秒输出一次统计信息。跑完后的输出里,你要重点关注三行:transactions(总事务数),queries(总请求数),latency统计里的95th percentile(95% 请求的延迟)。比如 128 线程压 10 张千万行表,QPS 能跑到 8000,95% 延迟在 20ms 以内,这个底座数据就算是比较健康的。
4.5 压测过程中的监控:没有监控的压测等于盲跑
压测开始之后,最忌讳的就是只盯着压测工具的统计面板。压测工具显示的响应时间只是"果",数据库端的资源消耗才是"因"。我建议至少开两个窗口:一个跑top看 CPU 和内存,一个开数据库的实时监控。MySQL 的话用SHOW ENGINE INNODB STATUS\G和SHOW PROCESSLIST;定期刷,Oracle 用TOP级别的等待事件视图,PostgreSQL 则用pg_stat_activity和pg_stat_database。
有一个监控指标我要特别强调:Threads_connected(已连接线程数)。当压测并发上升时,这个值会跟着涨,一旦接近max_connections的上限,新连接就会开始排队,应用端的表现就是连接池获取超时。很多"压测挂掉"的现场,根因都是连接数耗尽而不是数据库本身处理不过来。
我自己习惯把监控数据全程记录下来,每 5 秒采集一次,压测完整理成一张曲线图。这样最后汇报的时候,能清清楚楚看到 CPU 在什么时候飙到 100%、QPS 在什么时候到顶、响应时间在什么时候开始劣化——这些数据比压测工具自己算的平均值有价值得多。
4.6 写报告的骨架:数据支撑结论,结论指向行动
压测报告是压测工作的最终交付物,但很多人的报告写成了"数据堆砌"。一份好的压测报告,应该让看的人在 10 分钟内知道两件事:系统能不能扛住目标负载,如果扛不住,该怎么改。
我的报告结构一般是这样的:
- 压测目标与结论摘要:先写结论,比如"系统在 3000 QPS 下稳定运行,TP99 250ms,达到目标;6000 QPS 下出现明显劣化,建议扩容或优化 SQL"。
- 测试环境说明:机器规格、数据库版本、关键参数配置、数据量。这一部分看起来枯燥,但它是结果可复现的前提。
- 测试场景与执行参数:线程数、爬坡方式、SQL 比例模型、压测时长。
- 关键指标曲线:QPS、响应时间、连接数、CPU、IO 的时序图,标注性能拐点位置。
- 瓶颈定位与优化建议:结合监控数据,给出"瓶颈在哪个环节、建议怎么改"的具体结论。
最后这一点尤其重要。压测报告不能只列"峰值 QPS 是 XXX"然后就没有然后了,一定要回答"这个数据说明了什么问题、下一步该干什么"。比如压测发现innodb_buffer_pool_size不够导致磁盘 IO 偏高,报告中就要直接给出建议:将该参数从 8G 调到 32G,再压一轮验证。
5. 结果怎么读:指标曲线与瓶颈定位方法
压测跑完只是开始,读懂数据才是重点。数据库压测的结果解读,核心是三个字:找拐点。所谓拐点,就是在某个负载水平下,系统的某一个指标开始急剧劣化,这个位置就是系统的容量极限。
5.1 读曲线,而不是读平均值
我见过太多人只看压测工具最后给的一个"Average Response Time",然后得出结论"平均 200ms,系统很健康"。这个结论是被平均数骗了。实际的情况往往是:前 80% 的请求响应时间只有 50ms,后 20% 的请求响应时间到了 800ms,平均下来看起来 200ms 还挺正常,但真实用户体验已经差了 16 倍。
所以读结果一定要看百分比延迟曲线:TP50、TP95、TP99。TP99 是 99% 请求都在该时间内完成的时间阈值,它是反映用户体验的黄金指标。如果 TP99 出现明显的向上翘的曲线,哪怕 TP50 还很平,系统也已经进入不稳定状态了。配合 QPS 曲线一起看:当 QPS 不再随着并发用户数上涨而上涨,反而开始持平或者下跌,同时 TP99 快速拉升,这个点就是典型的容量拐点。
5.2 瓶颈定位的四种典型场景
根据我压测的经验,数据库的性能瓶颈绝大多数落在以下四个位置。你压出异常数据后,先按这个顺序排查,大概率能找到根因。
场景一:CPU 打满,QPS 上不去。最典型的症状是top里%us(用户态占用)接近 100%,同时SHOW PROCESSLIST里一片Sending data状态。这种情况通常是 SQL 没有走索引,或者走了索引但过滤性差,导致大量无效页读取和行扫描。解决思路是先拿慢查询日志看执行计划,EXPLAIN分析是不是出现type=ALL全表扫描,然后通过加联合索引、改写 SQL、调整optimizer_switch等方式优化。
场景二:磁盘 IO 高,CPU 并不忙。这种现象在 HDD 环境里特别常见:数据库的innodb_buffer_pool_size太小,大部分热数据没进内存,每次查询都要从磁盘读页;或者写入量大导致 redo log 频繁刷盘。优化方向是加大 buffer pool(前提是物理内存足够),确保热数据全部驻留内存;如果写入密集,还需要评估 SSD 的必要性。SSD 和 HDD 在数据库场景下的 IO 能力差距可以达到 20 倍以上,很多时候换一块 SSD 比优化十条 SQL 都管用。
场景三:连接数耗尽,系统"拒绝服务"。现象是压测端报"Too many connections",数据库日志里出现connection refused。这种问题多半不在数据库本身,而是应用端的连接池配置不合理——比如连接池上限设得过大,导致高峰期瞬间创建了大量连接,把数据库打满;或者连接用完后没有正确归还,泄漏掉了。解决办法是双管齐下:应用端的连接池上限要控制住,数据库端的max_connections也要留足余量。我常说的一个比例是:数据库max_connections设为应用连接池大小的两倍再加 50,基本能覆盖各种波动。
场景四:锁等待导致响应时间拉长。这个坑比较隐蔽。症状是压测的整体 QPS 不算低,但 TP99 异常高,SHOW ENGINE INNODB STATUS里能看到大量LOCK WAIT信息。典型的触发场景是压测脚本里有大批量大事务,长时间持锁,导致后续的小事务全部排队。解决办法是先定位具体持锁的 SQL,拆事务、缩事务,把大批量操作分批提交,同时检查业务逻辑中是不是存在慢查询在事务中间执行(比如事务里查了一个大表,把锁持有时间拉长了几百倍)。
5.3 稳定性压测:看泄漏和衰减
除了短时容量压测,还应该跑一轮稳定性压测。方法很简单:用 50% 到 70% 的容量上限,持续跑 4 到 8 小时,重点观察三件事——内存是否持续增长不回落(内存泄漏)、连接数是否居高不下(连接泄漏)、QPS 是否随时间推移逐渐衰减(缓存命中率下降 / 死锁累积 / 临时表膨胀)。稳定性问题比容量问题更隐蔽,因为它在短时间压测里完全不会暴露,但一上线跑个三五天就会出事。我的实际经验是:如果稳定压测中发现内存曲线一路向上不带回头的,基本可以断定某个连接池的对象没有被正常释放,这一类问题必须在上线前查清楚。
6. 最容易翻车的四个场景与规避办法
聊了这么多方法和理论,最后分享四个我在实际操盘中踩过或者看别人踩过的坑。每一个都是真实发生过的,写在最后希望大家避开。
6.1 拿测试环境的配置参数去估算生产容量
这是我见过最多、也是最致命的错误。压测环境和生产环境配置不同,压出来的数字直接套用到生产,结果必然失真。比如压测库的innodb_buffer_pool_size只有 4G,生产库配了 64G,那么压测结果里磁盘 IO 一定偏高,QPS 也明显偏低。反过来,如果压测用的机器比生产还好,压出来数据漂亮,上线后同样流量下响应时间直接翻倍,团队就懵了。
规避办法:压测前先做一个"环境系数校准"——用同一个标准 SQL(比如一条简单的SELECT COUNT(*) FROM 大表)分别在压测环境和生产环境跑十次,算出一个性能差异系数。压测结果除以这个系数,得到的分值才是比较接近生产真实水平的估算值。这个办法不完美,但至少不会让团队产生"我看不懂压测报告"的迷茫。
6.2 压测完库表被撑爆,影响业务库
压测的时候数据量是千万甚至亿级,事务日志、binlog、undo log 都很占空间。如果压测环境和其他应用公用磁盘,或者跑完压测忘了清理压测产生的临时数据,很可能把磁盘空间耗尽,波及同一台机器上的其他业务。
规避办法:压测前检查磁盘剩余空间,确保至少有压测数据量两倍以上的余量;压测环境尽量独立;压测完成后必须执行清理脚本,把压测库和对应的 binlog 一并处理掉。我在团队里定的规矩是:每次压测结束,压测负责人必须在日志里写清楚"压测数据已清理、磁盘空间剩余 XX G",谁清理、什么时候清理的,都要留痕。
6.3 压测脚本参数错误导致"假压测"
这个坑特别好笑,但特别常见。有一次我用 JMeter 压测,线程组配置了 500 个并发用户,压了 20 分钟,数据库端Threads_connected显示连接数从没超过 40。查了半天,发现 JDBC Connection Configuration 里的 Max Pool Size 被我设成了 20,JMeter 本身启动了 500 个线程,但只有 20 个连接可用,剩下 480 个线程全在排队等连接。你以为你压了 500 并发,实际数据库只承受了 20 并发。
规避办法:压测开始前,先进数据库看一眼SHOW PROCESSLIST;,确认连接的来源 IP 数量和压测线程数对得上。别省这一步,两秒钟的事,能救你一下午的无效压测。类似的检查还包括:确认压测机的ulimit没有限制文件句柄数、确认网络带宽没有被别的任务抢了。
6.4 只测功能不测数据一致性
最后要说的是一个理念问题。压力测试不仅是在测"快不快",也是在测"在极端负载下数据对不对"。并发写入时会不会出现死锁导致的回滚?大批量删除时会不会锁表导致其他表读写停滞?主从同步能不能跟上主库的压力?这些都属于压测的范畴。我之前压过一套订单系统,在 2000 并发写入场景下,主从延迟一度涨到 30 秒,意味着从库查出来的数据滞后严重,此时应用即使没有报错,业务上也可能已经出现了可见的脏读。
规避办法:在压测场景中加入数据一致性校验脚本,压测结束后对比总行数、关键字段汇总值,验证有没有异常丢失或重复。主从架构的系统,还要同时监控Seconds_Behind_Master指标,它和主库 QPS 一起看,能直观反映复制链路的能力上限。
数据库压测这件事,说难也难,说简单也简单。难在它需要理解业务、懂数据库原理、会看监控、能解析指标,简单在一旦你按流程走通一次,后面就是熟能生巧的活。说到底,压测不是去证明系统有多强,而是去提前发现系统会在哪里跪下——在用户还没来的时候让它跪,总好过在上线后当着所有人的面跪。