MySQL监控与慢SQL解决思路实时监控语句耗时与SQL状态
使⽤语句show full processlist; 此命令有权限,⾃⼰的账号只能看⾃⼰的连接,root账号可以看全部连接。
字段值说明
Id整数连接和会话的唯⼀ID
User 字符
哪个⽤户使⽤了此连接或者会话
Host 字符
由那个ip的客户端连接到服务的
db 字符
数据库名称
Command 字符
连接执⾏命令状态,例如:⼀般就是休眠(sleep),查询(query),连接(connect)
Time整数空闲或者执⾏语句时间,如果是空闲,这个时间代表空闲了多久。如果是执⾏,那就是这个sql执⾏所经过的时间(sql执⾏的太久属于不正常现象)
State 字符
详细见下⽅state字段描述
Info 字符
如果是执⾏就显⽰正在执⾏的sql语句。因为长度有限,所以长的sql语句就显⽰不全,但是⼀个判断问题语句的重要依据。
state字段描述
显⽰使⽤当前连接的sql语句的状态,很重要的列,可⽤来判断mysql的运⾏状态。 这个命令中最关键的就是state列,mysql列出的状态主要有以下⼏种:
Checking table
 正在检查数据表(这是⾃动的)。
Closing tables
 正在将表中修改的数据刷新到磁盘中,同时正在关闭已经⽤完的表。这是⼀个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
 复制从服务器正在连接主服务器。
Copying to tmp table on disk
 由于临时结果集⼤于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
 正在创建临时表以存放部分查询结果。
deleting from main table
 服务器正在执⾏多表删除中的第⼀部分,刚删除第⼀个表。
deleting from reference tables
 服务器正在执⾏多表删除中的第⼆部分,正在删除其他表的记录。
Flushing tables
 正在执⾏FLUSH TABLES,等待其他线程关闭数据表。
Killed
 发送了⼀个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下⼀个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过⼀⼩段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上⽣效。
Locked
 被其他查询锁住了。
Sending data
 正在处理Select查询的记录,同时正在把结果发送给客户端。
Sorting for group
 正在为GROUP BY做排序。
Sorting for order
 正在为ORDER BY做排序。
Opening tables
 这个过程应该会很快,除⾮受到其他因素的⼲扰。例如,在执Alter TABLE或LOCK TABLE语句⾏完以前,数据表⽆法被其他线程打开。正尝试打开⼀个表。
Removing duplicates
 正在执⾏⼀个Select DISTINCT⽅式的查询,但是MySQL⽆法在前⼀个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
 获得了对⼀个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
 修复指令正在排序以创建索引。
Repair with keycache
 修复指令正在利⽤索引缓存⼀个⼀个地创建新索引。它会⽐Repair by sorting慢些。
Searching rows for update
 正在讲符合条件的记录出来以备更新。它必须在Update要修改相关的记录之前就完成了。
Sleeping
 正在等待客户端发送新请求.
System lock
 正在等待取得⼀个外部的系统锁。如果当前没有运⾏多个mysqld服务器同时请求同⼀个表,那么可以通过增加--skip-external-locking 参数来禁⽌外部系统锁。
Upgrading lock Insert DELAYED
正在尝试取得⼀个锁表以插⼊新记录。
Updating
 正在搜索匹配的记录,并且修改它们。
User Lock
 正在等待GET_LOCK()。
Waiting for tables
 该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下⼏种情况下会产⽣这个通知:FLUSH TABLES tbl_name, Alter TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。 waiting for handler insert
Insert DELAYED
已经处理完了所有待处理的插⼊操作,正在等待新的请求。  ⼤部分状态对应很快的操作,只要有⼀个线程保持同⼀个状态好⼏秒钟,那么可能是有问题发⽣了,需要检查⼀下。
杀死连接
语法为kill id; 例:kill 62532 使⽤⽅式是使⽤show full processlist ⼈⼯判断出锁表的会话,使⽤kill杀死此会话。不只是锁表的需要杀死,可能某些建⽴索引的,或者特别耗时的sql也需要杀死,原则就是⽆法很快处理掉的会话都需要杀死,如果不杀死可能会严重拖慢mysql的效率⽽造成死机,更多的慢sql等等,
记录导出慢SQL⽇志
通过
sql优化的几种方式SHOW VARIABLES LIKE '%slow_query_log%' ;
查看是否开启了慢sql⽇志以及⽇志位置。 配置my.ini⽂件(Linux下⽂件名为myf), 查到[mysqld]区段,增加⽇志的配置,如下⽰例:
1[mysqld]
2slow_query_log = 1;  #开启
3slow_query_log_file=/var/lib/mysql/slow_query.log    #慢⽇志地址,缺省⽂件名host_name-slow.log
4long_query_time=5;  #运⾏时间超过该值的SQL会被记录,默认值>10,单位s(秒)
5log_output=FILE
Linux下这些配置项应该已经存在,只是被注释掉了,可以去掉注释。 未使⽤索引的查询被记录到慢查询⽇志中。如果调优的话,建议开启这个选项。如果开启了这个参数,full index scan的sql也会被记录到慢查询⽇志中。
1show variables like '%log_queries_not_using_indexes%'
2set global log_queries_not_using_indexes=1
分析慢查询⽇志
mysqldumpslow 慢⽇志分析⼯具。 命令: -s 按照那种⽅式排序 c:访问计数 l:锁定时间 r:返回记录 al:平均锁定时间 ar:平均访问记录数 at:平均查询时间 -t 是top n的意思,返回多少条数据。 -g 可以跟上正则匹配模式,⼤⼩写不敏感。 得到返回记录最多的20个sql:
mysqldumpslow -s r -t 20 sqlslow.log
得到平均访问次数最多的20条sql:
mysqldumpslow -s ar -t 20 sqlslow.log
得到平均访问次数最多,并且⾥⾯含有ttt字符的20条sql:
mysqldumpslow -s ar -t 20 -g "ttt" sqldlow.log
注: 如果出现如下错误,Died at /usr/bin/mysqldumpslow line 161, <> chunk 405659.说明你要分析的sql⽇志太⼤了,请拆分后再分析 拆分的命令为:
tail -100000 mysql-slow.log>mysql-slow.20180725.log
pt-query-digest,为另外⼀款慢sql分析⼯具,也推荐使⽤。 Mysqlsla,功能最全⾯的慢sql分析⼯具。
执⾏计划与慢SQL分析
Explain分析 Explain是Mysql的⾃带查询优化器,负责select语句的优化器模块,可以模拟优化器执⾏SQL查询语句,从⽽知道Mysql是如何处理SQL的,语法也很简单:Explain + SQL。 以下是通过explain查询出的⼏个属性
(常见性能瓶颈 —— CPU:CPU饱和⼀般发⽣在数据装⼊内存或从磁盘上读取数据时 IO:磁盘I/O瓶
颈发⽣在装⼊数据远⼤于内存容量时 服务器硬件的性能瓶颈:top,free,iostat,vmstat来查看系统的性能状态) ⽤途: (1)表的读取顺序,id (2)数据读取操作的操作类型,select_type (3)哪些索引可以使⽤ (4)哪些索引被实际使⽤ (5)表之间的引⽤ (6)每张表有多少⾏被优化器查询 rows
id:反映的是表的读取的顺序,或查询中执⾏select⼦句的顺序。 ⼩表永远驱动⼤表,三种情况: (1)id相同,执⾏顺序是由上⾄下的
(2)id不同,如果是⼦查询,id序号会递增,id值越⼤优先级越⾼,越先被执⾏ (3)id存在相同的,也存在不同的,所有组中,id越⼤越
先执⾏,如果id相同的,从上往下顺序执⾏
derived是衍⽣虚表的意思,derived2中的2对应id2 select_type:反映的是Mysql理解的查询类型 (1)simple:简单的select查询,查询中不包含⼦查询或union。 (2)primary:查询中若包含任何复杂的字部分,最外层查询标记为primary。 (3)subquery:select或where列表中的⼦查询。 (4)derived(衍⽣):在from列表中包含的⼦查询,Mysql会递归执⾏这些⼦查询,把结果放在临时表⾥。 (5)union:若第⼆个select出现在union后,则被标记为union,若union包含在from字句的⼦查询中,外层select将被标记为derived (6)union result:union后的结果集
table:反映这⼀⾏数据是关于哪张表的
type:访问类型排序反映sql优化的状态,⾄少达到range级别,最好能达到ref查询效率:system > const > eq_ref > ref > range > index > all   (完整的排序:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >all)  (1)system:从单表只查出⼀⾏记录(等于系统表),这是const类型的特例,⼀般不会出现 (2)const:查询条件⽤到了常量,通过索引⼀次就到,常在使⽤primary key或unique索引中出现。
where id=1写死,所以类型是
const (3)eq_ref:唯⼀性索引扫描,对于每个索引键,表中只有⼀条记录与之匹配,常见于主键或唯⼀索引扫描。 (4)ref:⾮唯⼀性索引扫描,返回匹配某个单独值的所有⾏,本质上也是⼀种索引访问,它可能会到多个符合条件的⾏,与eq_ref的差别是eq_ref只匹配了⼀条记录。 (5)range:只检索给定范围的⾏,使⽤⼀个索引来选择⾏。key列显⽰使⽤了哪个索引,⼀般是在where语句中出现了between、<、>、in等的查询。这种范围扫描索引扫描⽐全表扫描要好,因为它只需要开始于索引的某⼀点,⽽结束于另⼀点,不⽤扫描全部索引。与eq_ref和ref的区别在于筛选条件不是固定值,是范围。
(6)index:full Index
scan,index和all的区别为index类型只遍历索引树。这通常⽐all快,因为索引⽂件通常⽐数据⽂件⼩。
要获得的id信息,刚好id在索引上,从索引中读取(all和index都是读全表,但index是从索引中读取的,⽽all是从硬盘中读的) (7)all:全表扫描,如果查询数据量很⼤时,全表扫描效率是很低的。
possible_keys、key、key_len:反映实际⽤到了哪个索引,索引是否失效 (1)possible_keys:Mysql推测可能⽤到的索引有哪些,但不⼀定被查询实际使⽤ (2)key:实际使⽤的索引,若为null,则可能没建索引或索引失效。
(查询中若使⽤了覆盖索引,则该索引仅出现在key列表中。   覆盖索引:select后⾯的字段和所建索引的个数、顺序⼀致) (3)key_len:表⽰索引中使⽤的字节数,可通过该列计算查询中使⽤的索引的长度。同样的查询结果下,长度越短越好。 key_len显⽰的值为索引字段的最⼤可能长度,并⾮实际使⽤长度,即key_len是根据
表定义计算⽽得,不是通过表内检索出的。
ref:反映哪些列或常量被⽤于查索引列上的值
rows:根据表统计信息及索引选⽤情况,⼤致估算出到所需的记录所需要读取的⾏数
仅通过主键索引查
是641⾏
建完相关的复合索引
再查,需要查询的⾏数就变少了
Extra (1)using filesort:mysql中⽆法利⽤索引完成的排序,这时会对数据使⽤⼀个外部的索引排序,⽽不是按照表内的索引顺序进⾏读取。
创建索引时就会对数据先进⾏排序,出现using filesort⼀般是因为order by后的条件导致索引失效,最好进⾏优化。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。