《MySql学习》 Select 查询语句慢的非性能原因

一.查询被阻塞

A会话执行 查询操作,长时间没有返回信息,此时我们就可以去排查一下是否是被阻塞了

select * from words 

image-20230228144716163

被阻塞的原因有很多,首先列举第一种情况

1.等MDL锁

当我们执行DDL语句时,会自动给表加上MDL写锁。当执行DML和DQL时,会给表加上MDL读锁。

对MDL锁来说,读读共享,读写互斥。 因此,有可能会话A正在执行DDL语句,并且事务未提交。此时会话B执行DQL语句,那么会话B将被阻塞,查询语句长时间没有返回。

如果出现这种现象,我们可以查询到等待MDL锁的现象

show processlist

image-20230228145752891

但是 id : 86 是我们的查询语句,想找出是哪个会话ID造成的查询语句堵塞,还得使用下面的语句

select * from sys.schema_table_lock_waits

image-20230228150201424

此时可以看到是 87 阻塞了我们的查询语句,把它kill掉即可

2.等待 Flush

flush tables words with read lock;

flush tables with read lock;

flush 表示 关闭所有已打开的表对象,同时将查询缓存中的结果清空。就是说Flush tables的一个效果就是会等待所有正在运行的SQL请求结束。 因为,SQL语句在执行前,都会打开相应的表对象,如select * from t1语句,会找到t1表的frm文件,并打开表内存对象。为了控制表对象使用的内存空间和其他资源,MySQL会隐式(后台表对象管理线程)或显式(flush tables等)来关闭已打开但并没有使用的表对象。 然而,正在使用的表对象是不能关闭的(如SQL请求仍在运行),因此,Flush Tables操作会被正在运行的SQL请求阻塞。

3.等行锁

当执行下面的语句获取最新的值时,将有可能被阻塞 (普通读不会加锁,并不会阻塞)

select * from words w  where id = 1 lock in share mode ;

img

如上图所示,此时 session B 将被阻塞

如需找出死锁的会话ID,可以通过下面的SQL进行排查

select * from sys.innodb_lock_waits;

image-20230228151911380

2.undo log导致查询慢

img

如上图所示,由于MySQL 的MVCC多版本并发控制实现,session b 将产生大量的 undo.log 日志

导致执行 select * from t where id =1(一致性读)需要遍历100W次并判断才能找到自己能读到的数据

而 select * from t where id =1 lock in share mode (当前读) 的速度将会很快,因为当前读不需要遍历版本链

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋日的晚霞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值