通过 show status 命令了解 SQL 执行次数
首先,我们可以使用 show status
命令查看服务器状态信息。show status 命令会显示每个服务器变量 variable_name 和 value,状态变量是只读的。如果使用 SQL 命令,可以使用 like 或者 where 条件来限制结果。like 可以对变量名做标准模式匹配。
SHOW STATUS LIKE 'Com%'
这里需要注意一下 show status 命令中可以添加统计结果的级别,这个级别有两个
- session 级: 默认当前链接的统计结果
- global 级:自数据库上次启动到现在的统计结果
SHOW GLOBAL STATUS
对于 show status 查询出来的统计结果,有两类参数需要注意下,一类是以 Com 为开头的参数,一类是以 Innodb 为开头的参数
Com_xxx 表示的是每个 xxx 语句执行的次数,我们通常关心的是 select 、insert 、update、delete 语句的执行次数,即
- Com_select:执行 select 操作的次数,一次查询会使结果 + 1。
- Com_insert:执行 INSERT 操作的次数,对于批量插入的 INSERT 操作,只累加一次。
- Com_update:执行 UPDATE 操作的次数。
- Com_delete:执行 DELETE 操作的次数。
以 Innodb_ 为开头的参数主要有 - Innodb_rows_read:执行 select 查询返回的行数。
- Innodb_rows_inserted:执行 INSERT 操作插入的行数。
- Innodb_rows_updated:执行 UPDATE 操作更新的行数。
- Innodb_rows_deleted:执行 DELETE 操作删除的行数。
通过上面这些参数执行结果的统计,我们能够大致了解到当前数据库是以更新(包括插入、删除)为主还是查询为主。
除此之外,还有一些其他参数用于了解数据库的基本情况。 - Connections:查询 MySQL 数据库的连接次数,这个次数是不管连接是否成功都算上。
- Uptime:服务器的工作时间。
- Slow_queries:慢查询次数。
- Threads_connected:查看当前打开的连接的数量。
这个大佬整理的一份非常全的
http://www.ttlsa.com/mysql/mysql_show_status_descriptsions/
定位执行效率较低的 SQL
可以通过慢查询日志来定位哪些执行效率较低的 SQL 语句。
MySQL 中提供了一个慢查询的日志记录功能,可以把查询 SQL 语句时间大于多少秒的语句写入慢查询日志,日常维护中可以通过慢查询日志的记录信息快速准确地判断问题所在。用 --log-slow-queries 选项启动时,mysqld 会写一个包含所有执行时间超过 long_query_time 秒的 SQL 语句的日志文件,通过查看这个日志文件定位效率较低的 SQL 。
比如我们可以在 my.cnf 中添加如下代码,然后退出重启 MySQL。
log-slow-queries = /tmp/mysql-slow.log
long_query_time = 2
通常我们设置最长的查询时间是 2 秒,表示查询时间超过 2 秒就记录了,通常情况下 2 秒就够了,然而对于很多 WEB 应用来说,2 秒时间还是比较长的。
慢查询日志会在查询结束以后才记录,所以在应用反应执行效率出现问题的时候慢查询日志并不能定位问题,此时应该使用 show processlist
命令查看当前 MySQL 正在进行的线程。包括线程的状态、是否锁表等,可以实时的查看 SQL 执行情况。
查看执行线程
processlist命令的输出结果显示了有哪些线程在运行,不仅可以查看当前所有的连接数,还可以查看当前的连接状态帮助识别出有问题的查询语句等。
如果是root帐号,能看到所有用户的当前连接。如果是其他普通帐号,则只能看到自己占用的连接。SHOW PROCESSLIST
只能列出当前100条。如果想全部列出,可以使用SHOW FULL PROCESSLIST
命令。
mysql> show full processlist;
+----+------+--------------------+------+---------+-------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+--------------------+------+---------+-------+-------+-----------------------+
| 1 | root | localhost | NULL | Sleep | 19 | | NULL |
| 2 | root | 192.168.100.1:7437 | test | Sleep | 8042 | | NULL |
| 3 | root | 192.168.100.1:7438 | NULL | Sleep | 24355 | | NULL |
| 5 | root | 192.168.100.1:7443 | NULL | Sleep | 24324 | | NULL |
| 7 | root | 192.168.100.1:7450 | test | Sleep | 24279 | | NULL |
| 9 | root | 192.168.100.1:5152 | test | Query | 0 | init | show full processlist |
+----+------+--------------------+------+---------+-------+-------+-----------------------+
6 rows in set
各个列的含义:
id列,用户登录mysql时,系统分配的"connection_id",可以使用函数connection_id()查看
user列,显示当前用户。如果不是root,这个命令就只显示用户权限范围的sql语句
host列,显示这个语句是从哪个ip的哪个端口上发的,可以用来跟踪出现问题语句的用户
db列,显示这个进程目前连接的是哪个数据库
command列,显示当前连接的执行的命令,一般取值为休眠(sleep),查询(query),连接(connect)等
time列,显示这个状态持续的时间,单位是秒
state列,显示使用当前连接的sql语句的状态,很重要的列。state描述的是语句执行中的某一个状态。一个sql语句,以查询为例,可能需要经过copying to tmp table、sorting result、sending data等状态才可以完成
info列,显示这个sql语句,是判断问题语句的一个重要依据
State 列非常重要,关于这个列的内容比较多,读者可以参考一下这篇文章
https://blog.csdn.net/weixin_34357436/article/details/91768402
这里面涉及线程的状态、是否锁表等选项,可以实时的查看 SQL 的执行情况,同时对一些锁表进行优化。