首页 > 数据库 >MySQL 分析查询与来源机器

MySQL 分析查询与来源机器

时间:2023-08-28 21:35:12浏览次数:44  
标签:statements setup 查询 performance MySQL 机器 events schema

当前分析针对版本:MariaDB 10.5

线上出现报错:can't create more than max_prepared_stmt_count statements。造成这个错误的直接原因就是同时开启了 prepare 句柄太多导致的,所以比较直接的方式是调大参数,首先查看设置的值:

show global variables like 'max_prepared_stmt_count';

如果这个值比较小,我们需要手动调大:

set global max_prepared_stmt_count=1048576;

或者也可以修改配置文件,不过需要重启。

配置好之后我们注意观察下面几个参数的变化:

show global status like 'com_stmt%';

主要涉及下面的 3 个参数:

  1. Com_stmt_close 表示 prepare 语句关闭的次数
  2. Com_stmt_execute 表示 prepare 语句执行的次数
  3. Com_stmt_prepare 表示语句 prepare 的次数

注意这些参数,正常来说 3 者应该差不多,如果打开的和关闭的差距越来越大,那说明可能存在很多 statement 没有关闭,如果一直增长直到出现上面的报错,那说明肯定有程序存在 bug,忘记的关闭 statement 最终导致超出了限制。

如果程序比较少,应该很容易排查,但是如果操作当前 MySQL 实例的程序比较多,就需要从数据库角度来分析了。

第一种方法可以开启日志追踪打印所有 SQL 执行的情况:

set global general_log = 'ON';

这样所有的 SQL 执行情况都会打印出来,我们需要从日志中找到没有 close 的 prepare 从而定位问题,但是如果 SQL 特别多同时日志中有没有客户端来源,看日志会非常麻烦,不容易分析问题。

然后第二种方法就是开启性能追踪,首先需要确认性能追踪模式是否开启:

SHOW VARIABLES LIKE 'performance_schema';

如果没有开启,这个参数是无法直接动态开启的,因为这个是只读的变量,必须通过配置文件修改:

[mysqld]
performance_schema=ON

保存配置后,确定在不影响生产环境的前提下重启数据库:

systemctl restart mariadb

重启后我们需要开启下面这些性能追踪相关的表:

use performance_schema;
show tables like '%statement%';

我们主要用到下面这几个表:

  1. events_statements_current 当前正在执行查询的表
  2. events_statements_history 最近的10个完成的查询,通过 performance_schema_events_statements_history_size 可以调整大小,限制在 1024 之内
  3. events_statements_history_long 最近的1万个完成的查询,具体通过参数 performance_schema_events_statements_history_long_size 配置大小,限制在 1048576 之内

表结构参考:https://mariadb.com/kb/en/performance-schema-events_statements_current-table/

我们需要确认 setup_instruments 和 setup_consumers 中是否开启采集:

select * from setup_instruments where name like "statement/%";
-- 如果 enabled 是 NO 则可以开启
update setup_instruments set enabled="YES" where name like "statement/%";

确认 setup_consumers 中是否开启:

select * from setup_consumers;
-- 开启参数
update setup_consumers set enabled='YES' where name in ('events_statements_current', 'events_statements_history', 'events_statements_history_long');

表结构参考:https://mariadb.com/kb/en/performance-schema-setup_consumers-table/

开启后如果有查询我们在对应的事件表中应该可以查询到结果,也可以编写一个程序执行 prepare 单不要关闭,此时我们就可以通过 events_statements_current 表查询到具体的 SQL。

那么最后我们应该怎么找到是哪个客户端发起的查询呢?我们注意到上面的查询事件表中都有 THREAD_ID 字段,如果想看到具体正在进行的查询可以查询 processlist 表,那么这时候 threads 表就可以将 THREAD_ID 和 PROCESSLIST_ID 给关联起来,也就是说我们此时应该通过 threads 表通过 THREAD_ID 查询得到 PROCESSLIST_ID。

threads 表结构参考:https://mariadb.com/kb/en/performance-schema-threads-table/

然后我们查询具体的任务来源:

show processlist;
select * from information_schema.processlist where ID=<PROCESSLIST_ID>;

这样就可以找到具体查询来源的客户端了,processlist 表结构参考:https://mariadb.com/kb/en/information-schema-processlist-table/

我们可以通过 join 实现组合查询,快速找到出现问题的 SQL 来源,然后就可以基于机器和端口号进一步找到客户端进程的具体位置,从而方面定位问题。

Reference:

  1. https://stackoverflow.com/questions/26660763/mysql-performance-schema-not-working-properly
  2. https://www.cnblogs.com/Courage129/p/14188422.html

标签:statements,setup,查询,performance,MySQL,机器,events,schema
From: https://www.cnblogs.com/freeweb/p/17663429.html

相关文章

  • 查询SQL Server数据库执行时间最长的sql语句
    SELECT(total_elapsed_time/execution_count)/1000N'平均时间ms',total_elapsed_time/1000N'总花费时间ms',total_worker_time/1000N'所用的CPU总时间ms',total_physical_readsN'物理读取总次数',total_logical_reads/execution_countN'每次......
  • Arch中使用Qt6的QtSql出现mysql driver not loaded的解决记录
    查阅了网上的说法,出现这个错误的原因大致可能有以下几种:Qt和mysql的位数不一样,一个是32位的,一个是64位的Qt中自带的驱动库与所使用的版本不匹配代码写错了,比如"QMYSQL"写成了"MYSQL"我出现个问题的原因是第二种。参考了一位老哥的博客QTMacM1解决mysqldrivernotloade......
  • MySQL的连接和导出数据分析和lift曲线
    MySQL的连接和使用https://www.cnblogs.com/zdstudy/p/16567399.htmlmysql使用网址https://blog.csdn.net/LikiLyn/article/details/120385981多个文件mergeimportpandasaspdimportnumpyasnpimportpymysql#%%打开数据库连接conn=pymysql.connect(host='地址',user......
  • mysql日志追踪 / 数据恢复
    1.查看日志开启状态showvariableslike'log_%';2.查看日志文件列表showbinarylogs;或者showmasterlogs;3.查看当前日志index位置showmasterstatus;4.查看binlog关键事件showbinlogevents[IN'log_name'][FROMpos][LIMIT[offset,]row_c......
  • MySQL online DDl原理
    onlineDDL从5.6开始,不阻塞DML但是会阻塞所有的DDL,online有三种模式:INSTANT(8.0.12),INPLACE(rebuild),INPLACE(no-rebuild),具体操作如下:1、只修改表的元数据信息删除二级索引修改索引名(5.7)修改字段名设置(删除)字段的默认值增加varchar长度,如果表示字符串长度的字节数变化则会使用c......
  • Python查询Prometheus API
     #!/bin/python#-*-coding:utf-8-*-importpandasaspdimportrequests,time,redefgetcolumn(status):iffloat(status)<80:return"正常"#eliffloat(status)<2:#return"异常"else:......
  • 《MySQL命令行客户端》的使用方法
    MySQL客户端连接工具有多种,但最常用的是MySQL命令行客户端。下面是MySQL命令行客户端的语法:mysql-hhostname-uusername-ppassword-Ddatabase_name其中:-h 参数指定要连接的MySQL服务器的主机名或IP地址。-u 参数指定要连接的MySQL服务器的用户名。-p 参数提示输......
  • MySqlBulkCopy 批量新增数据
    MySqlConnector有个MySqlBulkCopy批量新增数据方法,不过只能用DataTable,需要把list转成DataTable代码如下:MySqlBulkCopymySqlBulkCopy=newMySqlBulkCopy(conn){DestinationTableName="userinfo"};mySqlBulkCopy.ColumnMappings.AddRange(table.Columns.Cast<DataC......
  • 无法对表进行任何操作了,mysql
    现象:无法对表进行任何操作,比如truncatetable,比如select,一直处于等待状态。看起来像是表被锁了。 解决过程:1.查询占用中的查询:showOPENTABLESwhereIn_use>0;结果是0行数据,表明没有任何查询在占用。2.查询当前的所有事务select*frominformation_schema.in......
  • MySQL 8.0字符集校正
    MySQL升级为8.0版本时,之前版本的字符集往往是不同的,需要校正。执行下面的三个SQL语句的查询结果,可以从库、表、列三个层面对字符集进行校正。库selectconcat('alterdatabase',schema_name,'defaultcharactersetutf8mb4collateutf8mb4_general_ci;')frominform......