草庐IT

MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选

张永清 2023-03-28 原文

1  、MySQL数据库的性能监控

1.1、如何查看MySQL数据库的连接数

连接数是指用户已经创建多少个连接,也就是MySQL中通过执行 SHOW  PROCESSLIST命令输出结果中运行着的线程个数的详情,如图所示。

SHOW PROCESSLIST默认情况下只显示前100条记录的详情,如果超过100条后需要显示所有,可以通过执行SHOW  FULL  PROCESSLIST命令,如图所示。

 

show variables like 'max_connections'可以查询数据库中可以支持的最大连接数,如图所示。

本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

 show global status like 'max_used_connections'可以查询当前已经使用过的最大连接数,如图所示。

 1.2、如何查看MySQL数据库当前运行的事务与锁

事务是对数据库执行一种带有原子性、一致性、隔离性、持久性的数据操作,在MySQL中如果需要使用事务,那么数据存储时必须选用MySQL的innodb引擎,使用innodb引擎后,在MySQL系统数据库information_schema的innodb_trx表中记录了数据库当前正在运行的事务。

innodb_trx表中包含的常用字段说明如表所示。

表 innodb_trx表中包含的常用字段说明

字段

描述

trx_id

事务ID

trx_state

事务的状态,一般包括RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING着几种不同的状态

trx_started

事务开始运行的时间

trx_requested_lock_id

事务需要等待的但已经被别的程序锁定的资源id,一般可以和INNODB_LOCKS表关联在一起获取更多的被锁定的资源的详细信息

trx_wait_started

事务开始等待时间

trx_mysql_thread_id

事务对应的MySQL线程id

trx_query

事务正在执行的SQL语句

trx_operation_state

事务操作的状态

trx_tables_in_use

事务使用到的数据库表的数量

trx_tables_locked

事务锁定的数据库表的数量

trx_rows_locked

事务锁定的数据记录行数

trx_rows_modified

事务更改的数据记录行数

trx_unique_checks

事务是否打开唯一性检查的标识

 

trx_foreign_key_checks

事务是否打开外键检查的标识

 

trx_isolation_level

事务隔离级别,一般分为Read Uncommitted(未提交读取)、Read Committed(已提交读取)、Repeatable Read(可重复读取)、Serializable(序列化)四种不同的级别

trx_weight

事务的权重

trx_lock_memory_bytes

事务锁住的内存大小,单位为 字节

trx_concurrency_tickets

事务并发票数

trx_last_foreign_key_error

 

事务最后一次的外键检查的错误信息

 

MySQL系统数据库information_schema的 innodb_locks表中记录了innodb数据库引擎当前产生的锁的情况, innodb_locks表中包含的常用字段说明如表所示。

字段

描述(本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

lock_id

锁的id

lock_trx_id

拥有锁的事务 ID。可以和 INNODB_TRX 表关联查询得到事务的详细信息

lock_mode

锁的模式,锁的模式一般包含:

行级锁:包括S(共享锁)、X(排它锁)、IS(意向共享锁)、IX(意向排它锁)。

表级锁:包括S_GAP(共享间隙锁)、X_GAP(排它间隙锁)、IS_GAP(意向共享间隙锁)、IX_GAP(意向排它间隙锁) 和 AUTO_INC(自动递增锁)

lock_type

锁的类型。包括RECORD(行级锁)和TABLE(表级锁)

lock_table

当前被锁定的或者包含锁定记录的表的名称

lock_index

当 LOCK_TYPE为RECORD 时,表示锁定的索引的名称,否则直接返回NULL

lock_space

当 LOCK_TYPE为RECORD 时,表示锁定行的表空间 ID,否则直接返回NULL

lock_page

当 LOCK_TYPE为RECORD时,表示锁定记录行的页数,否则直接返回NULL

lock_rec

当 LOCK_TYPE为RECORD时,表示锁定的数据行的数量

lock_data

当 LOCK_TYPE为RECORD时,表示锁定记录行的主键

MySQL系统数据库information_schema的innodb_lock_waits表中记录了innodb数据库引擎当前运行的数据库事务等待锁的情况,innodb_lock_waits表中包含的常用字段说明如表所示。本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

表innodb_lock_waits表中包含的常用字段说明

字段

描述

requesting_trx_id

请求事务的 ID

Requested_lock_id

事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表关联查询

Blocking_trx_id

阻塞事务的 ID

Blocking_lock_id

阻塞了另一事务的运行的事务的锁的 ID

在数据库中出现死锁时,经常需要通过查询innodb_trx、innodb_locks、innodb_lock_waits这三张表来找出在执行什么事务操作时导致了死锁,例如执行如下SQL可以列出数据库中所有事务的等待和锁定记录。

--本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  
--来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》
SELECT
r.trx_isolation_level,/*事务隔离级别*/ r.trx_id AS waiting_trx_id,/*正处于等待中的事务id*/ r.trx_mysql_thread_id AS waiting_trx_thread, /*正处于等待中的数据库线程id*/ r.trx_state AS waiting_trx_state, /*正处于等待中的事务的状态*/ lr.lock_mode AS waiting_trx_lock_mode,/*正处于等待中的事务的锁定模式*/ lr.lock_type AS waiting_trx_lock_type,/*正处于等待中的事务的锁定类型*/ lr.lock_table AS waiting_trx_lock_table,/*正处于等待中的事务将锁定的表*/ lr.lock_index AS waiting_trx_lock_index,/*正处于等待中的事务将锁定的索引*/ r.trx_query AS waiting_trx_SQL,/*正处于等待中的事务将执行的SQL*/ b.trx_id AS blocking_trx_id,/*正处于锁定中的事务id*/ b.trx_mysql_thread_id AS blocking_trx_thread,/*正处于锁定中的线程id*/ b.trx_state AS blocking_trx_state,/*正处于锁定中的事务的状态*/ lb.lock_mode AS blocking_trx_lock_mode,/*正处于锁定中的事务的锁定模式*/ lb.lock_type AS blocking_trx_lock_type,/*正处于锁定中的事务的锁定类型*/ lb.lock_table AS blocking_trx_lock_table,/*正处于锁定中的事务已经锁定的表*/ lb.lock_index AS blocking_trx_lock_index,/*正处于锁定中的事务已经锁定的索引*/ b.trx_query AS blocking_sql /*正处于锁定中的事务在执行的SQL*/ FROM information_schema.innodb_lock_waits wt INNER JOIN information_schema.innodb_trx b ON b.trx_id = wt.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = wt.requesting_trx_id INNER JOIN information_schema.innodb_locks lb ON lb.lock_trx_id = wt.blocking_trx_id INNER JOIN information_schema.innodb_locks lr ON lr.lock_trx_id = wt.requesting_trx_id;

1.3、MySQL中数据库表的监控

  •  1、查看数据库中当前打开了哪些表: show OPEN TABLES ,如图所示。另外还可以通过show OPEN TABLES where In_use > 0过滤出当前已经被锁定的表。

  •  2、查看数据库中表的状态:SHOW STATUS LIKE  '%table%',如图所示。需要特别注意的是Table_locks_waited  指的是不能立即获取表级锁而需要等待的次数,如果等待的次数非常大则说明可能存在锁争抢的情况,如果是频繁的出现锁争抢则对应用程序的并发性能影响很大。

 

  • 3、查看数据库中锁的信息:SHOW STATUS LIKE '%lock%',如图所示。

 

  • 4、查看数据库中的表被扫描的情况:show global status like 'handler_read%',如图所示,查询的结果数据也可以用来评估数据库中索引的使用情况。查询的结果数据说明如表所示。

 

查询结果项

描述

Handler_read_first

从索引中读取第一项的次数,如果该值非常高,表明服务器正在执行大量的全索引扫描,该值一般不宜太高

Handler_read_key

基于键读取数据行的请求数,该值如果越高则表明大量的查询都走了索引。如果越低,表示索引的利用很低,该值一般越高越好

Handler_read_last

读取索引中最后一个键的请求数

Handler_read_next

按键顺序读取下一行的请求数,如果查询都走了索引,那么该值将不断递增

Handler_read_prev

按键顺序读取前一行的请求数(倒序读取数据),一般用于评估执行ORDER BY … DESC的次数

Handler_read_rnd

基于固定位置读取数据行的请求数,如果正在执行大量的需要对查询结果进行排序的查询,则此值很高。如果该值很高,则可能存在很多查询需要做整表扫描或者查询时一些表的关联连接没有正确使用主键或者索引

Handler_read_rnd_deleted

从数据库数据文件中读取被删除记录行的请求数

Handler_read_rnd_next

从数据库数据文件中读取下一行的请求数,如果SQL语句执行大量表扫描,则此值很高。如果该值很高,一般说明表没有正确添加索引或者SQL语句没有走索引来查询

1.4、性能测试时MySQL中其他常用监控 

  • 1、查看每秒事务的提交数:show global status like 'com_commit',如图所示

 

  • 2、查看每秒事务的回滚数:show global status like 'com_rollback',如图所示

 

  •  3、查看线程的运行情况:show global status like 'threads_%',如图所示。

查询结果描述说明如表所示。

表查询结果描述说明

查询结果项

描述

Threads_cached

线程缓存中的线程数

Threads_connected

已经建立连接的线程数

Threads_created

已经创建的线程数

Threads_running

正在运行中的线程数

  • 4、查看数据库建立过的连接总数(包括连接中以及已经断开的连接):show global status like 'Connections',如图所示。

  •  5、查看innodb引擎缓存命中情况:show global status like 'innodb_buffer_pool_read%',如图所示。

  • 6、 查看join操作时全表扫描的次数:show global status like 'select_full_join',如图所示,该值一般可以表示SQL语句中的join操作没有走索引的次数,如果值非常大,那可能是SQL语句中的join操作存在性能问题。

  • 7、 查看SQL中排序使用情况:show global status like 'sort%',如图所示

  • 8、 查看SQL查询缓存的命中情况:show global status like 'qcache%',如图所示。

如果需要查询数据库查询缓存的设置,可以通过show variables like 'query_cache%'进行查看,如图所示。

备注:MySQL数据库中大部分的运行状态都可以通过show status和show global status来查看,二者的区别在于前者是查询当前的运行状态,后者是查询全局的运行状态,也就是数据库开始启动运行到现在为止的状态。

2、MySQL数据库的性能定位

2.1、慢SQL

慢SQL 一般指查询很慢的SQL语句,在MySQL数据库中,可以通过慢查询来查看所有执行超时的SQL语句,在默认情况下,一般慢SQL 是关闭的,可以通过执行show variables like 'slow_query%'来查看数据库是否开启了慢查询,如图所示。

从图中看到slow_query_log的值为OFF表示未开启,可以通过执行 set global slow_query_log=1; 或者 set global slow_query_log=ON;来临时开启慢查询,如图所示。

如果需要永久开启,需要修改/etc/my.cnf配置文件,在[mysqld]处加入如下配置,然后重启数据库即可生效,如图所示。

slow_query_log=ON

slow_query_log_file=/var/lib/mysql/localhost-slow.log

 

修改完成重启数据库后,再次执行show variables like 'slow_query%',发现慢查询已经被开启,如图所示。

 

通过执行show variables like 'long_query%';可以查询慢查询的记录时间,如图所示,默认是10秒,可以通过执行set long_query_time=需要修改的时长;来修改慢查询的记录时间。

 

通过执行show status like 'slow_queries';可以查看慢查询发生的次数,如图所示。

从慢查询日志中,我们也可以看到慢查询发生的详细信息,如图所示,慢查询日志中会记录每次慢查询发生的时间、执行查询时的数据库用户、线程id、查询执行的SQL语句等信息。

本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

在获取到慢查询的SQL语句后,就可以借助数据库的执行计划来对慢查询的SQL语句做进一步分析了。

 2.2、执行计划

在MySQL中使用explain关键字可以模拟查看数据库是如何来执行SQL查询语句,也就是常说的查看一条SQL语句在数据库中的执行计划,如图6-2-8所示就是执行EXPLAIN

本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

SELECT * FROM  test.test 后返回的SELECT * FROM  test.test查询的执行计划。

 

查询结果返回的字段说明如表所示 

表查询结果返回的字段说明

字段

说明

id

查询的顺序编号,表示查询中执行的顺序,id的值越大执行的优先级越高,如果id相同,则从上往下执行

select_type

查询类型,常见查询类型如下:

SIMPLE:表示简单查询方式,SQL语句中一般不会不使用UNION和子查询等

PRIMARY:表示当查询中包含子查询时,最外层的查询语句则被标记为primary 。

UNION:查询语句中如果在UNION关键字之后出现了第二个SELECT,则被标记为UNION。

UNION RESULT:表示查询中有多个查询结果集做UNION操作。

DEPENDENT UNION:表示子查询中存在UNION操作时,从UNION之后的第二个及之后的SELECT语句都是DEPENDENT UNION。

DEPENDENT SUBQUERY:子查询中UNION 中第一个SELECT查询为DEPENDENT SUBQUERY。

SUBQUERY:子查询内层查询的第一个SELECT。

DERIVED:查询语句中如果from子句的子查询中出现了union关键字则外层select查询将被标记为DERIVED。

MATERIALIZED:表示子查询被物化。

UNCACHEABLE SUBQUERY:表示查询结果集无法缓存的子查询,需要逐次查询。

UNCACHEABLE UNION:表示子查询不可被物化,需要逐次运行

Table

查询涉及的表名或者表的别名

本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

Type

表示表连接的类型,包括的类型如下所示,如下的这些类型的性能从高到低的顺序是:null→system→const→eq-ref→ref→fulltext→ref_or_null→index_merge→unique_subquery→index_subquery→range→index→ALL

null:表示不访问任何的表

system:表示表中只有一条记录,相当于系统表,一般可以认为是const类型的特例。

const:表示主键或者唯一索引的常量查询,表中最多只有1行记录符合查询要求,通常const使用到主键或者唯一索引进行定值查询、常量查询,查询的速度非常快。

eq_ref:表示join 查询过程中,关联条件字段走主键或者唯一索引,出来的行数不止一行。eq_ref是一种查询性能很高的 join 操作。

ref:表示非聚集索引的常量查询

fulltext:表示查询的过程中,使用到了 fulltext 索引。

ref_or_null:跟ref查询类似,在ref的查询基础上会多家一个null值的条件查询

index merg:表示索引联合查询,

unique subquery:表示查询走主键的子查询

index subquery:表示查询走非聚集索引的子查询

range:表示查询走索引范围的查询,一般包括:=、<>、>、>=、<、<=、IS NULL、BETWEEN、IN、<=> 等范围。

index:表示通过索引做扫描查询。

All:表示全表扫描,性能最差

possible_keys

查询时预计可能会使用的索引,这里说的索引只是可能会用到,实际查询不一定会用到。

Key

实际查询时真实使用的索引

key_len

使用的索引长度

Ref

关联信息

Rows

查询时扫描的数据记录行数

Extra

表示查询特性的使用情况,常用的查询特性如下所示。

Using index:表示使用了索引

Using index conditio:表示使用了索引做过滤

Using MRR:表示使用了索引做内部排序

Using where:表示使用了where条件

Using temporary:表示使用了临时表。

Using filesort:表示使用文件排序,一般指无法利用索引来完成的排序

本文作者:张永清, 转载请注明: https://www.cnblogs.com/laoqing/p/16880718.html  来源于博客园 ,本文摘选自《软件性能测试分析与调优实践之路》

 

 

有关MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  3. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  8. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  9. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  10. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

随机推荐