- orzdba查看读写
./orzdba.pl --mysql -S /data/mysql30001/mysql.sock 语句查看读写命令数量,以及数据库TPS,传输的大小 - 查看processlist及其state
mysql -uroot -p -S /data/mysql30001/mysql.sock, 密码sitMysql
或者mysql -usa_test -pymtcs@2016 -S /data/mysql30001/mysql.sockshow processlist; 该语句不显示全部语句
select * from information_schema.processlist;
查看当前进程的SQL语句,注意其STATE (以下一段引用百度)
在processlist中,看到哪些运行状态时要引起关注,主要有下面几个:
状态 建议
copy to tmp table 执行ALTER TABLE修改表结构时 建议: 放在凌晨执行或者采用类似pt-osc工具
Copying to tmp table 拷贝数据到内存中的临时表,常见于GROUP BY操作时 建议: 创建适当的索引
Copying to tmp table on disk 临时结果集太大,内存中放不下,需要将内存中的临时表拷贝到磁盘上,形成 #sql***.MYD、#sql***.MYI(在5.6及更高的版本,临时表可以改成InnoDB引擎了,可以参考选项 default_tmp_storage_engine ) 建议: 创建适当的索引,并且适当加大 sort_buffer_size/tmp_table_size/max_heap_table_size
Creating sort index 当前的SELECT中需要用到临时表在进行ORDER BY排序 建议: 创建适当的索引
Creating tmp table 创建基于内存或磁盘的临时表,当从内存转成磁盘的临时表时,状态会变成:Copying to tmp table on disk 建议: 创建适当的索引,或者少用UNION、视图(VIEW)之类的
Reading from net 表示server端正通过网络读取客户端发送过来的请求 建议: 减小客户端发送数据包大小,提高网络带宽/质量
Sending data 从server端发送数据到客户端,也有可能是接收存储引擎层返回的数据,再发送给客户端,数据量很大时尤其经常能看见备注:Sending Data不是网络发送,是从硬盘读取,发送到网络是Writing to net 建议: 通过索引或加上LIMIT,减少需要扫描并且发送给客户端的数据量
Sorting result 正在对结果进行排序,类似Creating sort index,不过是正常表,而不是在内存表中进行排序 建议: 创建适当的索引
statistics 进行数据统计以便解析执行计划,如果状态比较经常出现,有可能是磁盘IO性能很差建议: 查看当前io性能状态,例如iowait
Waiting for global read lock FLUSH TABLES WITH READ LOCK整等待全局读锁 建议: 不要对线上业务数据库加上全局读锁,通常是备份引起,可以放在业务低谷期间执行或者放在slave服务器上执行备份
Waiting for tables,Waiting for table flush FLUSH TABLES, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE等需要刷新表结构并重新打开 建议: 不要对线上业务数据库执行这些操作,可以放在业务低谷期间执行
Waiting for lock_type lock
等待各种类型的锁:• Waiting for event metadata lock• Waiting for global read lock
• Waiting for schema metadata lock
• Waiting for stored function metadata lock
• Waiting for stored procedure metadata lock
• Waiting for table level lock
• Waiting for table metadata lock
• Waiting for trigger metadata lock
建议:比较常见的是上面提到的global read lock以及table metadata lock,建议不要对线上业务数据库执行这些操作,可以放在业务低谷期间执行。如果是table level lock,通常是因为还在使用MyISAM引擎表,赶紧转投InnoDB引擎吧
综上,查询中有Creat sort index就是有问题,可以优化,
原语句为
SELECT FavoriteId, UserId, SourceId, AddTime, Type, SellerId, ProductId
FROM `App_UserFavorite`
WHERE `Userid` = 20000215 and `AddTime` < '2017-03-22 11:42:14.893' order by `FavoriteId` desc limit 10
优化为
explain SELECT FavoriteId, UserId, SourceId, AddTime, Type, SellerId, ProductId
FROM `App_UserFavorite`
WHERE `Userid` = 20000215 and `AddTime` < '2017-03-22 11:42:14.893' order by `AddTime` desc limit 10
优化后就没有 Creat sort index
3. 查看执行计划 explain
示例:
explain SELECT FavoriteId, UserId, SourceId, AddTime, Type, SellerId, ProductId
FROM `App_UserFavorite`
WHERE `Userid` = 20000215 and `AddTime` < '2017-03-22 11:42:14.893' order by `FavoriteId` desc limit 10
详细Extra:
Using index condition; Using where; Using filesort |
explain SELECT FavoriteId, UserId, SourceId, AddTime, Type, SellerId, ProductId
FROM `App_UserFavorite`
WHERE `Userid` = 20000215 and `AddTime` < '2017-03-22 11:42:14.893' order by `AddTime` desc limit 10;
对比两条语句的执行计划,发现第一条的Extra中用到东西多于第二条语句。
Explain具体分析查看: Mysql执行计划EXPLAIN详解
4. mysql profile 调试sql
(1) 打开profile
set profile on
set session profiling=1;
(2)执行相关语句,例如 :
SELECT FavoriteId, UserId, SourceId, AddTime, Type, SellerId, ProductId
FROM `App_UserFavorite`
WHERE `Userid` = 20000215 and `AddTime` < '2017-03-22 11:42:14.893' order by `FavoriteId` desc limit 10;
(3)查看profile队列中的语句
show profiles
对应的QueryId是28
(4)查看具体消耗
show profile for query 28; //28为QueryId
可以看出具体时间消耗
5. 查找慢查询
select * from mysql.slow_log where start_time >'2017-3-22 16:50:20'
mysql.slow_log中会放所有慢查询语句,所以需要 用start_time筛选下。找到慢查询语句,就可以用3,4的方法分析。
6. SPIN_Lock监控
当mysql的并发大时出现性能瓶颈,应用程序并发从1开始加到100的情况,应用每次请求会从Mysql拿下数据,下图是Mysql服务器的CPU占用状况
可以看到SystemTime的占用很高,这种情况一般是Linux底层_spin_lock过高引起的,这种情况下,一般认为mysql已到瓶颈,增大并发,并不能提高TPS
_spin_lock是内核级的自旋锁,每个Mysql process都会申请_spin_lock,具体原理,还有待研究
监控_spin_lock方法
(1)安装perf工具
yum install perf
(2)查看mysql进程号
top
(3)监控
perf top -p 3127