开启慢SQL的配置参数
slow_query_log: 该参数表示是否开启慢SQL查询日志。在mysql中,我们可以通过以下命令来查看和修改该变量的状态
1.show variables like ‘%slow_query_log%’ #查询该变量在MySQL中当前的状态。
2.set GLOBAL slow_query_log = ON/OFF #开启慢查询监控ON,关闭慢查询监控OFF
开启general_log执行日志
1.show variables like “general_log%”;#查询该变量在MySQL中当前的状态。
2.set GLOBAL general_log = ‘ON’;#开启执行日志监控ON,关闭执行日志监控OFF
long_query_time:设置该参数,可以规定执行多长时间的SQL为慢SQL。
1.show variables like ‘%long_query_time%’ #查询该变量在MySQL中的状态
2.set long_query_time = 6 #设置SQL执行时间超过6S,就当作慢SQL输出
slow_query_log_file:设置该参数,可以将慢SQL输出到指定的规定的日志文件。
1.show variables like ‘%slow_query_log_file%’ #查询该变量在MySQL中的状态
2.set slow_query_log_file = /home/admin/mysql/log/slow_sql.log #指定慢SQL输出的日志文件
log_queries_not_using_indexes:该参数设置为ON,可以输出所有未使用索引的SQL语句。
1.show variables like ‘log_queries_not_using_indexes’ #查询该变量在MySQL中的状态
2.set global log_queries_not_using_indexes = ON/OFF #设置该变量值打开或关闭
log_output:可以通过该参数,指定慢SQL输出到表或文件中。如果输出到表中在mysql.slow_log表中可以查看。
1.show variables like ‘log_output’ #查询该变量在MySQL中的状态
2.set GLOBAL log_output = table/FILE #设置慢SQL输出到table或file
3.set GLOBAL log_output = ‘table,FILE’ #设置慢SQL同时输出到table和file
从mysql的table中查看mysql日志
这要在上面中设置输出日志到table中,比如
set GLOBAL log_output = table/FILE #设置慢SQL输出到table或file同时输出到file和table中
1.select * from mysql.slow_log
这个是在mysql的库中
记录分析(mysqldumpslow)
1.mysqldumpslow -s t -t 10 -g ‘log’ mysql_slow.log
MySQL自带的慢SQL分析工具
-s : 按照哪种规则排序
-t: 显示前几个记录
-g : 有点像grep, 后跟正则
c: 访问计数
l: 锁定时间
r: 返回记录
t: 查询时间
al:平均锁定时间
ar:平均返回记录数
at:平均查询时间
demo如下
最好在mysql_slow.log前加全路径,这里的mysql-slow.log是之前设置的日志输出文件的路径下的文件名,默认就是mysql-slow.log
mysqldumpslow -s t -t 10 /var/lib/mysql/mysql-slow.log
得到返回记录集最多的10条SQL
1.mysqldumpslow -s r -t 10 /var/lib/mysql/mysql-slow.log
得到按照查询时间排序,并且带有left join的10条SQL
1.mysqldumpslow -s t -t 10 -g “left join” /var/lib/mysql/mysql-slow.log
查看正在运行的sql
1.select * from information_schema.processlist
demo
找出所有执行时间超过 5 分钟的线程,拼凑出 kill 语句,方便后面查杀 (此处 5分钟 可根据自己的需要调整SQL标红处)
1.select concat('kill ', id, ‘;’) from information_schema.processlist where Command != ‘Sleep’ and Time > 300 order by Time desc;
查询线程及相关信息
除了 root 用户能看到所有正在运行的线程外,其他用户都只能看到自己正在运行的线程,看不到其它用户正在运行的线程。除非单独个这个用户赋予了PROCESS 权限。
1.show full processlist
ID 为此线程ID,Time为线程运行时间,Info为此线程SQL
如果你的MySQL是源码编译的,那么慢SQL日志文件信息由编译时指定,比如:一般将慢SQL日志文件放在/data/mysql/目录下,文件名为hostname-slow.log。
如果你的MySQL是RPM安装的,那么慢SQL日志文件信息由MySQL配置文件/etc/my.cnf指定,打开配置文件,找到[mysqld]区段,增加日志配置,具体如下:
[mysqld]
log=“/var/lib/mysql/mysql.log”
log_slow_queries="/var/lib/mysql/hostname-slow.log"
long_query_time=2
log指定MySQL日志文件存放路径。
log_slow_queries指定慢SQL日志文件存放路径,此目录文件一定要有写权限。
long_query_time指定大于多长时间算慢SQL,单位秒。
注意,上述配置一定要加在[mysqld]后而不是[mysqld_safe]下面,否则不会生效。
配置完后,重启MySQL即可:
service mysqld restart
mysql> show variables like ‘slow%’;
±-----------------±------+
| Variable_name | Value |
±-----------------±------+
| slow_launch_time | 2 |
±-----------------±------+
| slow_query_log | ON |
±-----------------±------+
| slow_query_log_file | /var/lib/mysql/hostname-slow.log|
±-----------------±------+
二、慢SQL分析
慢SQL分析可以通过vi直接打开日志文件来做,但是这种方式还是比较原始,实际上慢SQL分析工具有很多种,常用的有如下几款:
1、mysqldumpslow
这是MySQL官方提供的慢SQL日志分析工具,安装好后,执行如下语句就能分析日志:
#mysqldumpslow /var/lib/mysql/hostname-slow.log
主要功能是统计不同慢SQL的如下指标:
count(出现次数) Time(执行最长时间/累计总耗费时间) Lock(等待锁的时间S) Rows(发送给客户端的总行数) 用户及SQL语句
慢SQL日志文件有时候记录数会比较多,那么mysqldumpslow提供了一些参数用于解决这些问题:
mysqldumpslow -s r -t 10 /var/lib/mysql/hostname-slow.log
上面命令会以查询时间来排序并显示前10条查询,其中,参数s表示排序选项(c:查询次数、r:返回记录行数、t:查询时间),参数t表示只显示top n条查询。
2、mysqlsla
这是由hackmysql.com提供的一款日志分析工具,该网站还提供了mysqlreport、mysqlidxchk等实用的mysql工具值得学习。
安装好后,执行如下命令就能分析日志了:
#mysqlsla -lt slow /var/lib/mysql/hostname-slow.log
该工具方便用户分析慢查询的原因,包括执行频率、数据量、查询消耗等,具体包含信息如下:
queries total(总查询次数) unique(去重后的SQL数量)
Sorted by(报表按照什么排序)
Gand Totals(慢SQL统计信息):Time(平均执行时间),Lock(等待锁时间),Rows Sent(总行数),Rows Examined(总扫描行数)
Count(SQL执行次数及占总慢SQL数量的百分比)
Time(执行时间):包括总时间、最小/最大时间、时间占总慢SQL时间的百分比
Lock Time(等待锁时间)
Rows Sent(行数统计):包括平均、最小/最大数量
Database(数据库)
Users(用户、IP、占所有用户执行SQL的百分比)
Query abstract(抽象后的SQL语句)
Query sample(SQL语句例子)
3、mysql-log-filter
google code上的开源分析工具,提供python和php两种脚本,可以点击这里下载。
执行如下命令就能分析日志:
#python mysql_filter_slow_log.py /var/lib/mysql/hostname-slow.log --no-duplicates --sort-execution-count --top=10
功能上类似于mysqldumpslow,但是多出了很多查询时间的统计信息,包括平均、最大、累计等,此外,还对输出内容排版和格式化。
4、myprofi
sourceforge上提供的纯php写的开源分析工具,可以点击这里下载。
执行如下命令就能分析日志:
#php parser.php -slow /var/lib/mysql/hostname-slow.log
执行上面命令后,会列出总的慢查询次数和类型、去重后的SQL语句、执行次数及占总慢SQL数量的百分比。
myprofi的输出比较简洁,适合于只关心慢SQL语句及执行次数的同学。
SQL优化是一门大工程,不敢狂言,在此只是表述我实际中遇到的问题及优化解决方案来以此达到抛砖引玉的效果。
1、索引问题
在一次压力测试中,发现有一个70W记录的流水表,由于没有加索引导致在update时MySQL服务器CPU瞬间飙到170%,语句类似于下面:
update loginlog set LogoutTime=%lu where RoleName=%s and LoginTime=%lu
loginlog表的主键是自增ID。
对字段RoleName和LoginTime建索引后,问题解决了。
因此,对于操作频繁的select、update、带where的delete语句最好对where条件涉及的字段建索引,当然这也会给insert语句带来一定的性能损失。
2、联合主键问题
在一次压力测试中,在慢SQL日志中发现一条记录:
复制代码代码示例:
Time Id Command Argument
#Time: 130528 10:45:19
#User@Host: qa_root[qa_root] @ [172.28.14.224]
#Query_time: 0.003057 Lock_time: 0.000026 Rows_sent: 2 Rows_examined: 2262
use friend_relation;
SET timestamp=1369709119;
SELECT FromRoleName FROM userrelation WHERE ToRoleName = ‘xxx’;
userrelation中FromRoleName与ToRoleName为联合主键,但是上面的where语句中联合主键并没有达到效果。
这是因为,联合主键在索引时,where条件对字段及顺序有要求,比如:
复制代码代码示例:
(1)where FromRoleName=‘xxx’
(2)where FromRoleName=‘xxx’ and ToRoleName = ‘xxx’
上述两种情况都有效果。
为字段ToRoleName建立索引后,问题解决了。
3、分页问题
有时候会对表格记录有limit操作的需求,这就涉及到分页问题,这里贴一段我的DBA同事曾给我的一段关于分页优化的建议吧:
(1)首次查询的时候缓存结果。这样情况就变得简单了,无论是结果条目的数量,总共的页面数量,还是取出其中的部分条目。
(2)不显示总共有多少条目。Google搜索结果的分页显示就用了这个特性。很多时候你可能看了前几页,就够了。那么我可以这样,每次我都把结果限制在500条(这个数据越大 资源消耗越大)然后你每次查询的时候,都查询501条记录,这样,如果结果真有501个,那么我们就显示链接 “显示下500条记录”。
(3)不显示总页面数。只给出“下一页”的链接,如果有下一页的话。(如果用户想看上一页的话,他会通过浏览器来回到上一页的)。那你可能会问我“不显示总页面数”怎么知道是不是有下一页呢?这里有一个很好的小技巧:你在每次显示你当前页面条目的时候你都多查询一条,例如你要显示第11-20个条目时,你就取出11-21条记录(多取一条,并不显示这多取的内容),那么当你发现第21条存在的时候就显示“下一页的链接”,否则就是末页了。这样你就不用每次计算总页面数量了,特别是在做缓存很困难的时候这样做效率非常好。
(4)估算总结果数。Google就是这么做的,事实证明效果很好。用EXPLAIN 来解释你的SQL,然后通过EXPLAIN的结果来估算。EXPLAIN结果有一列”row”会给你一个大概的结果。(这个办法不是处处都行,但是某些地方效果是很好的)这些办法可以很大程度上减轻数据库的压力,而且对用户体验不会有什么影响。