Mysql专栏 - 线上调优与压力测试

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
可观测监控 Prometheus 版,每月50GB免费额度
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Mysql专栏 - 线上调优与压力测试

前言


本节内容讲述线上的调优手段以及压力测试的相关工具,结合一些实际的命令参数,我们将会介绍运行结果的具体含义。本节内容为大致的介绍如何压力测试和如何阅读参数,具体的运行效果需要自己部署一台机器测试,关于这部分的内容受到不同的机器影响会出现完全不同的效果,需要实际测试所以没有进行记录。


概述


  1. 介绍常见的mysql系统性能分析指标,介绍吞吐量和机器的选择
  2. 压力测试工具的介绍,以及数据库压力测试的实战。
  3. 最后将会根据Linux系统的命令介绍如何阅读mysql服务器的性能
  4. 简单介绍Prometheus和Grafana 两个系统。


系统指标分析



小型系统:


小型并发系统不需要考虑其他条件,因为那种系统可能每隔几分钟才会有一波请求发到数据库上去,而且数据库里一张表也许就几百条、几千条或者几万条数据,数据量很小,并发量很小,操作频率很低,用户量很小,并发量很小,只不过可能系统的业务逻辑很复杂而已,对于这类系统的数据库机器选型,就不在我们的考虑范围之内了。


通常选择:


大多数情况下一般8核16G的机器部署的MySQL数据库,每秒抗个一两千并发请求是没问题的,但是如果并发量再高一些,假设每秒有几千并发请求,那么可能数据库就会有点危险了,因为数据库的CPU、磁盘、IO、内存的负载都会很高,数据库压力过大就会宕机。


吞吐量:


如果一个系统处理一个mysql请求需要1s,那么一分钟可能只处理100个请求,4核8G的机器部署普通的Java应用系统,通常每秒大致就是抗下几百的并发访问,但是同一个配置的机器可以从每秒一两百请求到每秒七八百请求都是有可能的,关键是看你每个请求处理需要耗费多长时间。


固态硬盘


因为数据库最大的复杂就在于大量的磁盘IO,他需要大量的读写磁盘文件,所以如果能使用SSD固态硬盘,那么你的数据库每秒能抗的并发请求量就会更高一些。


数据库压力测试



有了数据库之后,第一件事就是做压力测试:


什么是qps,什么是tps?


压测数据库,每秒能扛下多少请求,每秒会有多少请求,如果要判定性能可以通过下面的指标:


Qps:全称是 query per second,意味着数据库每秒可以处理多少个请求,一个请求就是一个sql语句,在mysql中意味着一秒可以处理多少个sql语句。

Tps全程是 transaction per second,Tps是用来衡量一个数据库每秒完成事务的数量,有一些人会把tps理解为数据库的每秒钟请求多数量,但是不太严谨。

每秒可以处理的事务量,这个数据用在数据库内部中用的比较多,意味着数据库每秒会执行多少次事务提交或者回滚。


Io的性能指标


关注的io相关性能指标,大家也要跟他做一个了解:

(1) IOPS:这个指的是机器的随机IO并发处理的能力,比如机器可以达到200 IOPS,意思就是说每秒可以执行200个随机 IO读写请求。

(2) 吞吐量:这个指的是机器的磁盘存储每秒可以读写多少字节的数据量

   (3) latency:这个指标说的是往磁盘里写入一条数据的延迟。

通常情况下一个普通磁盘的顺序写入都是可以到达200mb的请求上,通常而言,磁盘吞吐量都可以到200mb


通常情况下一块硬盘的读写延迟越低,数据库的性能就越高,执行sql和事务的速度就会越快。


压力测试的其他性能指标


  1. cpu负载:是一个重要的性能指标,假设数据库压测到了3000了,但是cpu负载已经满了,也就意味着它最多只能 处理这么多数据了。
  2. **网络负载:**压测到一定的qps或者tps的时候,每秒钟都机器网卡都输入多少mb数据,输出多少mb数据,qps1000的时候,网络负载打满了,每秒传输100mb到达上限也是无法压力测试的。
  3. 内存负载:机器的耗费到了极限也是不能压力测试的。


给你一台4核8G的机器,他可以扛住每秒几千甚至每秒几万的并发请求吗?

扛下多少请求,需要看实际的cpu,硬盘,内存,网络带宽等环境。一台机器扛下500+的请求已经很高了,如果每秒1000+请求,基本负载会打满。机器有可能挂掉。同时此时的内存也基本打满了,同时jvm的gc频率可能会非常高。


压力测试工具介绍



使用压力测试的工具是:sysbench工具


安装教程:


安装教程如下:


curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash 
sudo yum -y install sysbench
sysbench --version


数据库压测实战



下面是一个案例的指令,可以在使用的时候边运行结果对比了解:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_read_write --db-ps-mode=disable prepare


我们分别来介绍参数的内容:


--db-driver=mysql:这个很简单,就是说他基于mysql的驱动去连接mysql数据库,你要是oracle,或者sqlserver,那 自然就是其他的数据库的驱动了 
--time=300:这个就是说连续访问300秒--threads=10:这个就是说用10个线程模拟并发访 问
--report-interval=1:这个就是说每隔1秒输出一下压测情况
--mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=test_user --mysql-password=test_user:连接到哪台机器的哪个端口上的MySQL库,他的用户名和密码是什么
--mysql-db=test_db --tables=20 --table_size=1000000:这一串的意思,就是说在test_db这个库里,构造20个测试 表,每个测试表里构造100万条测试数据,测试表的名字会是类似于sbtest1,sbtest2这个样子的 oltp_read_write:这个就是说,执行oltp数据库的读写测试
--db-ps-mode=disable:这个就是禁止ps模式
--prepare 这个参数会按照设置构建测试需要的数据,自动创建20个表,每个表100万数据。


全方位测试


测试数据库的综合读写TPS,使用的是oltp_read_write模式(大家看命令中最后不是prepare,是run了,就是运行压测):


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_read_write --db-ps-mode=disable run


测试数据库的只读性能,使用的是oltp_read_only模式(大家看命令中的oltp_read_write已经变为oltp_read_only了):


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_read_only --db-ps-mode=disable run


测试数据库的删除性能,使用的是oltp_delete模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 --table_size=1000000 oltp_delete --db-ps-mode=disable run


使用上面的命令,sysbench工具会根据你的指令构造出各种各样的SQL语句去更新或者查询你的20张测试表里的数据,同时 监测出你的数据库的压测性能指标,最后完成压测之后,可以执行下面的cleanup命令清理数据:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_read_write --db-ps-mode=disable cleanup


测试数据库的更新索引字段的性能,使用的是oltp_update_index模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_update_index --db-ps-mode=disable run


测试数据库的更新非索引字段的性能,使用的是oltp_update_non_index模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_update_non_index --db-ps-mode=disable run


测试数据库的更新非索引字段的性能,使用的是oltp_update_non_index模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_update_non_index --db-ps-mode=disable run


测试数据库的插入性能,使用的是oltp_insert模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_insert --db-ps-mode=disable run


测试数据库的写入性能,使用的是oltp_write_only模式:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_write_only --db-ps-mode=disable run


最后完成压测之后,可以执行下面的cleanup命令清理数据:


sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysqlport=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 -table_size=1000000 oltp_read_write --db-ps-mode=disable cleanup


测试结果分析



下面是一个sysbench的运行结果:


[22s] thds: 10 tps: 380.99 qps: 7312.66 (r/w/o: 5132.99/1155.86/1321.35) lat (ms, 95%): 21.33 err/s: 0.00 reconn/s: 0.00


分析:


上面说的是第22s发生的事情,以及其他字段分别代表的含义:


Tdhs: 表示10个线程
Tps: 每秒执行了380个事务
Qps: 每秒执行了7312个请求
(r/w/o)…: 这一段内容表示7312.66个请求当中,有5132.99个是读请求。1155.86是写请求,1321个其他类型的请求。其实就是对整个qpsj你想拆分
Lat(ms, 95%): 意思是说,95%延迟在21.33毫秒以下
Err/s:每秒0个失败,发生了0次网络重连。


压测报告的解释


根据上面的压测命令在结果的最后是压测的整个报告,关于报告的内容其解释如下:


SQL statistics:queries performed:
  read: 1480084 
  // 这就是说在300s的压测期间执行了148万多次的读请求 write: 298457 
  // 这是说在压测期间执行了29万多次的写请求
  other: 325436 
  // 这是说在压测期间执行了30万多次的其他请求
  total: 2103977 // 这是说一共执行了210万多次的请求
  // 这是说一共执行了10万多个事务,每秒执行350多个事务 transactions: 105180( 350.6 per sec. )
  // 这是说一共执行了210万多次的请求,每秒执行7000+请求 queries: 2103977 ( 7013.26 per sec. )
  ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.)
  // 下面就是说,一共执行了300s的压测,执行了10万+的事务 General staticstics:
total time: 300.0052s
total number of events: 105180
Latency (ms):
  min: 4.32 
  // 请求中延迟最小的是4.32ms
  avg: 13.42 
  // 所有请求平均延迟是13.42ms
  max: 45.56 
  // 延迟最大的请求是45.56ms
  95th percentile: 21.33 
  // 95%的请求延迟都在21.33ms以内


其实压测就是用命令观察对应的情况用增加线程的手段试探机器的极限,另外一个就是通过linux的相关命令查看是否是正常情况。


命令查看压力测试性能:



Top:


top命令最直观展示cpu负载的,在linux执行top指令,我们可以看到下面的内容:


top 15:52:00 up 42:35, 1 user, load average: 0.15, 0.05, 0.01


下面是关于上面的结果内容展示:


这里指的是系统运行了42:35分钟,15:52指的是当前的时间,
1 user就是一个用户在使用
Load averatge 0.15, 0.05, 0.01 表示的则是cpu在 1分钟, 5分钟,15分钟的负载情况,假设一个4核心的cpu,负载时0.15,就是说4个核心一个核心都没用满。如果你的负载是1,说明4核有一个比较忙了


测时如何观察机器的内存负载情况?

  • Mem: 33554432k total, 20971520k used, 12268339 free, 307200k buffers
  • Top命令最后的内容是如下,总内存有32gb,已经使用了20gb,还有10多个是空闲的。


如何看磁盘io


使用dstat -d命令,会看到如下的东西:


-dsk/total read writ 103k 211k
0 11


在硬件的一定合理的负载范围内,把数据库的QPS提高到最大,这就是数据库压测的时候最合理的一个极限QPS值。


Prometheus和Grafana 两个系统


这两个系统请自行百度查阅了解和学习:

prometheus:是一个监控数据采集和存储系统,可以看作是定期从mysql中采集需要的监控数据。

granfana:适用于和prometheus进行辅助组合使用的,可以对于mysql进行一个可视化的监控动作。


思考题:


  1. 假设开发的Java系统部署在一台4核8G的机器上,那么我们假设这个Java系统处理一个请求非常非常快,每个请求只需要0.01ms就可以处理完了,那你觉得这一台机器部署的Java系统,可以实现每秒抗下几千并发 请求吗?可以实现每秒抗下几万并发请求吗?


答案来源:MySQL: 5 生产环境下的数据库机器配置_136.la

**答:**每个请求处理0.01ms,应该是不涉及磁盘的纯内存操作

在4核8G的机器上,也就是同时有4个线程数为最佳,多了反而会由于竞态问题导致频繁上下文切换,浪费性能。

理论上的并发请求数量

这里按照数据库使用3个线程,另一个CPU核心线程给其他进程使用。

在不考虑网卡资源的情况下,理论上可以实现每秒 3 * 1s/0.01ms = 30万请求。

生产环境下的影响因素

在真实生产环境下,还需要考虑很多的因素。生产环境必然不只是有4个线程在工作,那么就导致会存在CPU线程竞态切换的时间;当并发量高的时候还要算下内存消耗发生YGC和Full GC的STW时间也算进去;当并发很高,对CPU负载也很高,处理会变慢,此时TPS会很长。还有磁盘IO、网卡等因素也需要考虑进去。

此时,按照均值每个请求所需要的耗时可能达到100ms左右

  1. 关于QPS和TPS的。如果一个交易系统拆分为了很多服务,那么每个服务每秒接收的 并发请求是QPS还是TPS呢?

这个明显是QPS,因为每个服务就负责干自己的一些事儿,其实对他来说,每秒并发请求数量就是QPS。


总结


本次我们从简单的系统测试入手,介绍了影响mysql服务的指标,其实影响一个mysql服务性能的参数有很多,包括内存,处理器,io性能,网络带宽都有影响,所以不能完全按照理性化的配置去猜测数据库能承受多少压力,而是要根据压力测试对于数据库进行实际的压测之后,通过增加压力的方式找到mysql服务器的压力极限,最后通过两个思考题我们可以看到衡量一个mysql的性能需要从多方面考虑,哪怕是理想情况下能够处理的请求其实也不是很多。


写在最后


本文介绍的内容较为基础和简单,希望可以通过这篇文章引发更多关于mysql性能的思考。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
7月前
|
搜索推荐 API 开发者
京东商品列表 API 接口全解析:从入门到精通
京东商品列表API是京东开放平台为开发者提供的核心数据接口,支持批量获取商品基础信息、价格、库存状态等多维度数据。它具备数据丰富性、灵活筛选与分页查询、稳定高效等特点,可满足市场分析、选品优化、比价工具及推荐系统开发等需求,为电商业务创新提供坚实支撑。通过标准化通道,助力第三方高效、合法地利用京东海量商品数据。
|
9月前
|
并行计算 前端开发 异构计算
告别服务器繁忙,云上部署DeepSeek
本文以 DeepSeek-R1-Distill-Qwen-32B-FP8 为例,向您介绍如何在GPU实例上使用容器来部署量化的 DeepSeek-R1 蒸馏模型。
|
11月前
|
监控 安全 开发工具
鸿蒙HarmonyOS应用开发 | HarmonyOS Next-从应用开发到上架全流程解析
HarmonyOS Next是华为推出的最新版本鸿蒙操作系统,强调多设备协同和分布式技术,提供丰富的开发工具和API接口。本文详细解析了从应用开发到上架的全流程,包括环境搭建、应用设计与开发、多设备适配、测试调试、应用上架及推广等环节,并介绍了鸿蒙原生应用开发者激励计划,帮助开发者更好地融入鸿蒙生态。通过DevEco Studio集成开发环境和华为提供的多种支持工具,开发者可以轻松创建并发布高质量的鸿蒙应用,享受技术和市场推广的双重支持。
1768 11
|
5月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
1587 7
|
存储 消息中间件 NoSQL
【redis】redis的特性和主要应用场景
【redis】redis的特性和主要应用场景
698 2
|
人工智能 物联网
PiSSA :将模型原始权重进行奇异值分解的一种新的微调方法
我们开始看4月的新论文了,这是来自北京大学人工智能研究所、北京大学智能科学与技术学院的研究人员发布的Principal Singular Values and Singular Vectors Adaptation(PiSSA)方法。
286 3
|
负载均衡 安全 Java
Java一分钟之-WebSocket:实时通信协议
【6月更文挑战第1天】WebSocket是实现客户端与服务器长连接、双向通信的协议,简化实时数据传输。Java中的WebSocket实现基于JSR 356。本文涵盖WebSocket基础(持久连接、双向通信、低延迟)、工作流程、常见问题(安全、连接管理、数据编码)及Java实现示例,强调错误处理、心跳机制和资源管理的最佳实践。
876 6
|
存储 Python
数据包络分析(Data Envelopment Analysis, DEA)详解与Python代码示例
数据包络分析(Data Envelopment Analysis, DEA)详解与Python代码示例
|
SQL 关系型数据库 MySQL
MySQL - 左连接、右连接、内连接、完全外连接、交叉连接 & 一对多、多对一、多对多 & 联合连接
介绍MySQL中不同类型的SQL连接操作,包括左连接、右连接、内连接、完全外连接、交叉连接,以及数据库关系中的一对多、多对一、多对多和联合连接的概念和使用场景。
997 0
|
自然语言处理
论文推荐:用多词元预测法提高模型效率与速度
《Better & Faster Large Language Models via Multi-token Prediction》论文提出了一种多词元预测框架,改善了大型语言模型(LLMs)的样本效率和推理速度。该方法通过一次预测多个词元,而非单个词元,提高了模型在编程和自然语言任务中的性能。实验显示,多词元预测在HumanEval和MBPP任务上性能提升,推理速度最高可提升3倍。此外,自我推测解码技术进一步优化了解码效率。尽管在小模型中效果不明显,但该方法为大模型训练和未来研究开辟了新途径。
547 0