mysql查询语句执行慢分析
1.通过show processlist命令查看执行中的语句的状态
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 命令断开即可。
4.等行锁
select * from t where id=1 lock in share mode;或者 for update会被行上的写锁阻塞。
在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.
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的记录释放锁),这里会违背两阶段的约束。当然,之前每条记录的加锁操作还是不能省略的。