mysql查询语句执行慢分析

1.通过show processlist命令查看执行中的语句的状态

mysql查询语句执行慢分析

state显示在等表metadata锁(5.6及之前)表示表上正在执行表修改命令,持有了表的metadata写锁。阻塞查询语句的执行。

2.表被写锁锁住  lock table t write;

3.通过performance_schema和sys库进行判断

     mysql启动时需要设置performance_schema = on  性能上会有10%左右的损失

通过查询sys.schema_table_lock_waits表  我们就可以直接找出造成阻塞的 process id,把这个连接用 kill 命令断开即可。

mysql查询语句执行慢分析

4.等行锁

select * from t where id=1 lock in share mode;或者 for update会被行上的写锁阻塞。

mysql查询语句执行慢分析mysql查询语句执行慢分析mysql查询语句执行慢分析

mysql查询语句执行慢分析

在mysql 5.7也可以通过 

select * from t sys.innodb_lock_waits where locked_table='`test`.`t`'\G进行查询

 

5.慢查询 select * from t where c=50000 limit 1; 如果在c上没有索引,就会走全表扫描,导致慢查询

set long_query_time=n 会把查询时间超过n秒的查询写入慢查询日志

long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,Mysql数据库并不启动慢查询日志

相关配置:

slow_query_log    :是否开启慢查询日志,1表示开启,0表示关闭。

log-slow-queries  :旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log

slow-query-log-file:新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log  默认路径/usr/local/mysql/data/localhost-slow.log

long_query_time :慢查询阈值,当查询时间多于设定的阈值时,记录日志。

log_queries_not_using_indexes:未使用索引的查询也被记录到慢查询日志中(可选项)。

log_output:日志存储方式。log_output='FILE'表示将日志存入文件,默认值是'FILE'。log_output='TABLE'表示将日志存入数据库,这样日志信息就会被写入到mysql.slow_log表中。MySQL数据<br>库支持同时两种日志存储方式,配置的时候以逗号隔开即可,如:log_output='FILE,TABLE'。日志记录到系统的专用日志表中,要比记录到文件耗费更多的系统资源,因此对于需要启用慢查询日志,又需<br>要能够获得更高的系统性能,那么建议优先记录到文件。

 

日志分析工具mysqldumpslow

在实际生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具mysqldumpslow

查看mysqldumpslow的帮助信息:

mysqldumpslow --help

6.mysql查询语句执行慢分析mysql查询语句执行慢分析

sessionA的第一个语句因为要维护读取的版本,需要做100万次回滚操作,所以慢

但是第二个因为是一致性读直接读最新提交的值会很快(但是又锁等待的时间)

 

7.select * from t where c=5 for update 如果c上没有索引的时候
当级别为RR时,因为字段c上没有索引,会扫主键索引,这时会把表中的记录都加上X锁。同时,因为对于innodb来说,当级别为RR时,是可以解决幻读的,此时对于每条记录的间隙还要加上GAP锁。也就是说,表上每一条记录和每一个间隙都锁上了。
当级别为RC时,因为字段c上没有索引,会扫主键索引,这时会把表中的记录都加上X锁。

另外,MySQL在实际实现中有些优化措施,比如当RC时,在MySQL server过滤条件,发现不满足后,会把不满足条件的记录释放锁(这里就是把 c!=5的记录释放锁),这里会违背两阶段的约束。当然,之前每条记录的加锁操作还是不能省略的。