已经执行完的SQL,检查慢查询日志,日志中有执行慢的SQL
正在执行中的SQL,show processlist;
,结果中有执行慢的SQL
mysql> show variables like '%slow_query_log%'; +---------------------+----------------+ | Variable_name | Value | +---------------------+----------------+ | slow_query_log | OFF | | slow_query_log_file | bogon-slow.log | +---------------------+----------------+
mysql> show variables like '%long_query_time%'; +-----------------+-----------+ | Variable_name | Value | +-----------------+-----------+ | long_query_time | 10.000000 | +-----------------+-----------+
mysql> show global status like '%Slow_queries%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Slow_queries | 0 | +---------------+-------+
默认情况下,MySQL没有开启慢查询日志。需要手动打开
不建议开启,因为开启会带来一定的性能影响
不需要重启mysql,不区分系统,简单方便。重启mysql配置就失效了。
# 开启慢查询日志,只对当前数据库生效,并且重启数据库后失效 set global slow_query_log = 1;# 设置阈值 set long_query_time = 3;#设置慢日志文件 SET GLOBAL slow_query_log_file = '/mysql-slow.log';
修改配置文件my.cnf,新增如下内容。
完成配置后,需要重启MySQL服务器才能使配置生效。
[mysqld]## 开启慢查询日志,开启后将会记录执行时间超过 long_query_time 参数值的 SQL 语句( 一般临时开启即可 ) slow_query_log = 1## 定义执行时间超过多少秒为慢查询,默认 10s long_query_time = 1## 定义慢查询日志存放位置 slow_query_log_file = /data/mysql/logs/slow.log
#### slow log 慢查询日志 #### slow_query_log = 1 ## 开启慢查询日志 slow_query_log_file = slow.log ## 慢查询日志文件名称 long_query_time = 2 ##sql 语句超过2s就记录 min_examined_row_limit = 100 ## sql执行中examined_row 取出数据必须大于100行才会记录 log-queries-not-using-indexes ## 没有使用索引SQL的sql记录到慢查询 log_throttle_queries_not_using_indexes = 5 ## 限制每分钟记录没有使用索引Sql的次数 意思就是:一条sql语句一直在记录 记录太多了 占存储 一分钟只记录5次 log-slow-admin-statements = table ##记录管理的操作,例如alter | analyze talbe 命令 log_output = file ## 记录慢查询日志的格式 FILE|TABLE|NONE 默认是文件格式 TABLE 是以表的格式 不建议用table log_timestamps = 'system' ## 慢日志记录的时间格式 采用系统的时间
慢日志文件默认是在我们配置的data_dir目录下面的机器名+-slow.log文件
Time执行的时间 这里的时间时区是不对的,可以通过log_timestamps = system设置
Query_time是sql的运行时间,
Lock_time是sql锁住的时间
Row_wxamined: 表示这个sql读取行数
Rows_sent:返回的行总数
能将相同的慢SQL归类,并统计出相同的SQL执行的次数,每次执行耗时多久、总耗时,每次返回的行数、总行数,以及客户端连接信息等。
cd /data/mysql/install/bin/./mysqldumpslow --help
内容
[root@crc-uat-oa-mysql bin]# ./mysqldumpslow --help Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]Parse and summarize the MySQL slow query log. Options are --verbose verbose --debug 调试 --help 帮助文档 -v verbose -d 调试 # 表示按何种方式排序 -s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default al: 平均 锁定时间 ar: 平均 返回记录 at: 平均 查询时间 c: 访问次数 l: 锁定时间 r: 返回记录 t: 查询时间 -r 颠倒排序顺序(最大的最后一个而不是第一个) -t NUM 返回前面多少条数据 -a don't abstract all numbers to N and strings to 'S' -n NUM abstract numbers with at least n digits within names -g PATTERN 后面搭配一个正则匹配模式,大小写不敏感。 -h HOSTNAME 数据库服务器的主机名 for *-slow.log 文件,默认是 '*', 表示匹配所有 -i NAME 服务器实例的名称(如果使用mysql.server启动脚本 -l 不要从总时间中减去锁定时间
#锁定时间最长的前10条 mysqldumpslow.pl -s l -t 1 mysql_slow.log #得到返回记录集最多的10个SQL mysqldumpslow.pl -s r -t 10 mysql_slow.log #按照扫描行数最多的前10条 有left join 的语句 mysqldumpslow -s r -t 10 -g 'left join' /var/log/mysql/mysql-slow.log #得到访问次数最多的10个SQL mysqldumpslow.pl -s c -t 10 mysql_slow.log #按查询总时间排序,显示前10条查询信息取出查询时间最慢的10条慢查询)mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log #得到按照时间排序的前10条里面含有左连接的查询语句 mysqldumpslow -s t -t 10 -g “left join” /var/log/mysql/mysql-slow.log # 另外建议在使用这些命令时结合| 和more 使用,否则有可能出现爆屏情况 mysqldumpslow -s r -t 10 /data/mysql/logs/slow.log | more
其中,-s t 表示按查询总时间排序,-s c表示按查询次数排序,-t 10表示显示前10条查询信息。
widows下使用mysqldumpslow 可以参考:Windows下安装使用mysqldumpslow
explain关键参数
名称 | 解释 |
---|---|
key | 实际用到的索引列 |
type | 索引类型 |
extra | 额外信息 |
type部分值
名称 | 解释 |
---|---|
consts | 基于主键或唯一索引查询,最多返回一条数据,优化阶段可得到数据 |
ref | 基于普通索引的等值查询,表间等值连接 |
range | 利用索引范围查询 |
index | 全索引扫描 |
ALL | 全表操作 |
Extra部分值
名称 | 解释 |
---|---|
Using index | 使用覆盖索引,减少表扫描和回表 |
Using index condition | 先条件过滤索引再查询数据 |
Using filesort | 使用外部排序,非索引排序 |
Using where | 使用where条件 |
Impossible where | where总是false |
Using temporary | 使用临时表,一般发生在order by无索引列时 |
Using join buffer (Block Nested Loop) | 在进行嵌套循环连接,内表大 |
Select tables optimized away | 该查询不需要访问实际的表,而是通过优化方式直接计算出结果 |
select_type部分值
名称 | 解释 |
---|---|
Simple | 简单查询 |
Primary | 关联查询或子查询的外层查询 |
Unoin | 关联查询或子查询的后续查询 |
show processlist 其实查询的是 information_schema.processlist 表.
show processlist 不可以接 where 过滤,information_schema.processlist 表可以
show processlist 是显示用户正在运行的线程,需要注意的是,除了 root 用户能看到所有正在运行的线程外,其他用户都只能看到自己正在运行的线程,看不到其它用户正在运行的线程。除非单独个这个用户赋予了PROCESS 权限。
mysql> show processlist;
+----+------+-----------------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------+------+---------+------+----------+------------------+
| 51 | root | localhost:61246 | test | Sleep | 0 | | NULL |
| 52 | root | localhost:61342 | test | Query | 0 | starting | show processlist |
+----+------+-----------------+------+---------+------+----------+------------------+
2 rows in set (0.10 sec)
了解这些基本信息后,下面我们看看查询出来的结果都是什么意思。
Id: 就是这个线程的唯一标识,当我们发现这个线程有问题的时候,可以通过 kill 命令,加上这个Id值将这个线程杀掉。前面我们说了show processlist 显示的信息时来自information_schema.processlist 表,所以这个Id就是这个表的主键。
User: 就是指启动这个线程的用户。
Host: 记录了发送请求的客户端的 IP 和 端口号。通过这些信息在排查问题的时候,我们可以定位到是哪个客户端的哪个进程发送的请求。
DB: 当前执行的命令是在哪一个数据库上。如果没有指定数据库,则该值为 NULL 。
Command: 是指此刻该线程正在执行的命令。这个很复杂,下面单独解释
Time: 表示该线程处于当前状态的时间。
State: 线程的状态,和 Command 对应,下面单独解释。
Info: 一般记录的是线程执行的语句。默认只显示前100个字符,也就是你看到的语句可能是截断了的,要看全部信息,需要使用 show full processlist。
下面我们单独看一下 Command 的值:
Binlog Dump: 主节点正在将二进制日志 ,同步到从节点
Change User: 正在执行一个 change-user 的操作
Close Stmt: 正在关闭一个Prepared Statement 对象
Connect: 一个从节点连上了主节点
Connect Out: 一个从节点正在连主节点
Create DB: 正在执行一个create-database 的操作
Daemon: 服务器内部线程,而不是来自客户端的链接
Debug: 线程正在生成调试信息
Delayed Insert: 该线程是一个延迟插入的处理程序
Drop DB: 正在执行一个 drop-database 的操作
Execute: 正在执行一个 Prepared Statement
Fetch: 正在从Prepared Statement 中获取执行结果
Field List: 正在获取表的列信息
Init DB: 该线程正在选取一个默认的数据库
Kill : 正在执行 kill 语句,杀死指定线程
Long Data: 正在从Prepared Statement 中检索 long data
Ping: 正在处理 server-ping 的请求
Prepare: 该线程正在准备一个 Prepared Statement
ProcessList: 该线程正在生成服务器线程相关信息
Query: 该线程正在执行一个语句
Quit: 该线程正在退出
Refresh:该线程正在刷表,日志或缓存;或者在重置状态变量,或者在复制服务器信息
Register Slave: 正在注册从节点
Reset Stmt: 正在重置 prepared statement
Set Option: 正在设置或重置客户端的 statement-execution 选项
Shutdown: 正在关闭服务器
Sleep: 正在等待客户端向它发送执行语句
Statistics: 该线程正在生成 server-status 信息
Table Dump: 正在发送表的内容到从服务器
Time: Unused
下面是常用到的SQL,记录下来便于使用。
按客户端 IP 分组,看哪个客户端的链接数最多
select client_ip,count(client_ip) as client_num from (select substring_index(host,':' ,1) as client_ip from processlist ) as connect_info group by client_ip order by client_num desc;
查看正在执行的线程,并按 Time 倒排序,看看有没有执行时间特别长的线程
select * from information_schema.processlist where Command != 'Sleep' order by Time desc;
找出所有执行时间超过 5 分钟的线程,拼凑出 kill 语句,方便后面查杀
select concat('kill ', id, ';') from information_schema.processlist where Command != 'Sleep' and Time > 300 order by Time desc;
本文为崔凯原创文章,转载无需和我联系,但请注明来自冷暖自知一抹茶ckhttp://www.cksite.cn