你是否遇到过这些问题:
性能测试是提前发现这些问题的关键。通过模拟真实负载,我们能精准评估MySQL的极限能力、定位瓶颈,并验证优化效果。本文基于实战经验,整理出一套完整的MySQL性能测试模板,从环境搭建到结果分析,带你零基础掌握性能测试核心技能。
举例:电商场景需重点测试“商品详情页查询QPS”和“订单提交TPS”。
维度 | 核心指标 | 意义 |
---|---|---|
MySQL性能 | QPS(每秒查询数)、TPS(每秒事务数) | 数据库处理能力上限 |
响应时间 | 平均响应时间、95%/99%响应时间(ms) | 用户体验直接相关,避免长尾延迟 |
资源消耗 | CPU使用率、内存占用、磁盘IOPS/吞吐量 | 定位瓶颈(CPU/内存/IO) |
错误率 | 超时次数、连接失败率、锁等待次数 | 系统稳定性指标 |
关键原则:测试环境应与生产环境保持一致(至少配置比例一致)。
环境 | 配置详情 |
---|---|
CPU | 4核8线程(生产环境8核,则测试环境至少4核) |
内存 | 16GB(生产环境32GB,按比例缩减) |
磁盘 | SSD(避免用HDD,IO性能差异过大) |
MySQL版本 | 与生产一致(如8.0.32) |
配置文件 | 生产配置导出后修改(如 my.cnf ) |
避坑点:不要在本地Windows笔记本测试!虚拟机网络和IO性能会严重失真。
sysbench是MySQL官方推荐的基准测试工具,支持模拟多种负载场景:
# CentOS安装
yum install -y sysbench
# Ubuntu安装
apt install -y sysbench
# 验证安装
sysbench --version # 输出:sysbench 1.0.20+
# 安装系统监控工具
yum install -y sysstat # 提供iostat(磁盘IO)、vmstat(内存/CPU)
yum install -y iftop # 网络带宽监控
# MySQL性能监控(可选)
wget https://downloads.percona.com/downloads/percona-toolkit/3.5.1/binary/redhat/7/x86_64/percona-toolkit-3.5.1-1.el7.x86_64.rpm
rpm -ivh percona-toolkit-3.5.1-1.el7.x86_64.rpm # 含pt-query-digest(慢查询分析)
# 初始化10张表,每张100万行数据(模拟中型业务)
sysbench oltp_read_write \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--tables=10 \
--table-size=1000000 \
prepare
执行后,会生成sbtest1
到sbtest10
共10张表,每张表含id
、k
、c
、pad
字段,数据分布均匀。
如果需要模拟真实场景,可从生产环境导出部分数据(注意脱敏):
# 生产环境导出
mysqldump -uroot -p 生产库名 表名 --where "create_time >= '2025-01-01'" > data.sql
# 测试环境导入
mysql -uroot -p test_db < data.sql
测试前需调整MySQL配置(my.cnf
),避免因默认配置限制性能:
[mysqld]
# 内存配置(建议物理内存的50%-70%)
innodb_buffer_pool_size = 8G # 16GB内存服务器配置8G
# 事务日志(影响写入性能)
innodb_log_file_size = 1G # 不要超过4G
innodb_log_buffer_size = 64M
# 连接数(根据并发需求调整)
max_connections = 500
# 慢查询日志(记录测试中的慢SQL)
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # 超过1秒的查询记录为慢查询
修改后重启MySQL:systemctl restart mysqld
目标:找到MySQL在“纯读”“纯写”“读写混合”场景下的最大QPS/TPS。
模拟大量查询操作(如商品列表页、用户信息查询):
sysbench oltp_read_only \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--tables=10 \
--table-size=1000000 \
--threads=16 # 并发线程数(建议=CPU核心数*2,如8核设16)\
--time=60 # 测试时长(秒)\
--report-interval=10 # 每10秒输出一次中间结果\
run
关键输出解读:
SQL statistics:
queries performed:
read: 192000 # 读查询总数
write: 0 # 写查询总数
other: 27428 # 其他操作(COMMIT/ROLLBACK等)
total: 219428 # 总查询数
transactions: 13714 (228.56 per sec.) # TPS
queries: 219428 (3657.11 per sec.) # QPS
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 60.0011s
total number of events: 13714
Latency (ms):
min: 4.72
avg: 69.99
max: 325.08
95th percentile: 120.00 # 95%请求响应时间<120ms
sum: 959942.64
模拟大量插入/更新/删除(如订单创建、日志写入):
sysbench oltp_write_only \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--tables=10 \
--table-size=1000000 \
--threads=8 # 写操作CPU消耗低,线程数可设为CPU核心数\
--time=60 \
run
默认读写比例约7:3(可通过--ratio
参数调整):
sysbench oltp_read_write \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--tables=10 \
--table-size=1000000 \
--threads=32 \
--time=120 \
run
目标:测试真实业务SQL的性能(如首页复杂查询、报表统计)。
custom_test.lua
)-- 定义测试逻辑:随机查询id在1-1000000的记录
function event()
local id = math.random(1, 1000000)
-- 替换为你的业务SQL(如SELECT * FROM order WHERE id=?)
conn:query("SELECT * FROM sbtest1 WHERE id = " .. id)
end
sysbench --test=custom_test.lua \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--threads=20 \ # 模拟20个并发用户
--time=60 \
run
目标:验证max_connections
是否合理,避免连接数过高导致拒绝服务。
sysbench oltp_read_only \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=root \
--mysql-password=你的密码 \
--mysql-db=test_db \
--threads=200 # 模拟200并发连接(逐步增加,如50→100→200)\
--time=60 \
run
注意:若出现Too many connections
错误,需调大max_connections
或优化连接池(如使用ProxySQL)。
创建“性能测试结果表”,对比不同场景下的表现:
测试场景 | 并发线程 | QPS | TPS | 95%响应时间(ms) | CPU使用率(%) | 磁盘IOPS(写) | 结论 |
---|---|---|---|---|---|---|---|
纯读测试 | 8 | 3500 | - | 50 | 60 | 100 | 未达瓶颈 |
纯读测试 | 16 | 6800 | - | 90 | 90 | 200 | 接近CPU瓶颈 |
纯读测试 | 32 | 7000 | - | 150 | 100 | 250 | CPU已达瓶颈 |
读写混合测试(32线程) | 32 | 4500 | 900 | 200 | 95 | 800 | IO压力大 |
top
命令显示MySQL进程CPU使用率≥95%;vmstat 1
中 us+sy
(用户态+系统态CPU)≥95%;iostat -x 1
中 %util
(磁盘利用率)≥90%,await
(平均IO等待时间)≥20ms;innodb_buffer_pool_size
过小导致大量物理读。free -h
中 Swap
使用率持续上升;innodb_buffer_pool_size
设置过小,数据无法缓存到内存。explain
分析慢查询,添加索引(如ALTER TABLE t ADD INDEX idx_name (name)
);max_connections
,避免线程过多导致CPU上下文切换频繁;innodb_log_file_size
(如从512M→2G),减少日志刷盘次数;innodb_buffer_pool_size
(如物理内存的70%);某电商平台商品详情页查询卡顿,高峰期响应时间>500ms,用户投诉严重。
iostat
显示磁盘%util
=100%,await
=50ms(IO瓶颈);SELECT * FROM product WHERE category_id=?
未走索引。ALTER TABLE product ADD INDEX idx_category (category_id)
;innodb_buffer_pool_size
从4G→16G(服务器32G内存);product
表按category_id
分10个分区。%util
降至30%,await
=5ms;性能测试的终极目标不是“测出高指标”,而是“保障业务稳定运行”。希望本文的模板和方法,能帮助你避开性能坑,让MySQL跑得又快又稳!