MySQL查询中断后特定表无法访问,重启恢复,求助故障原因
分析你的MySQL表阻塞问题
让我一步步拆解你遇到的问题,核心原因其实都源于那个看似简单但效率极低的关联查询:
1. 你的查询本身是资源黑洞
你写的select count(*) from t1 join t2 where t1.id <> t2.id存在致命问题:没有指定JOIN的关联条件。这会让MySQL执行笛卡尔积关联——把t1的每一行和t2的每一行都进行匹配,50万行 × 50万行 = 250亿条临时记录!
这种级别的计算会瞬间榨干服务器的所有资源:
- CPU会被满负荷占用,用来处理海量的行匹配逻辑;
- 内存不足以存储临时数据时,MySQL会把数据写到磁盘临时表,导致磁盘IO疯狂飙升;
- 系统核心资源被耗尽后,自然会出现短暂宕机的情况。
2. 查询中断后的锁资源未正常释放
当查询执行300秒后被中断(错误码1317),MySQL需要清理这个超大查询留下的资源,但因为之前系统资源已被耗尽,这个清理流程可能没有正常完成:
- 元数据锁(MDL锁)滞留:执行SELECT时,MySQL会给表加MDL读锁,用于保护表结构不被意外修改。如果查询被强制中断,锁释放的逻辑可能因为资源不足而卡住,导致t1表的MDL锁一直被持有。后续你执行
select * from t1 limit 50时,需要获取MDL读锁,但前面的锁没释放,就会陷入无限等待,表现为t1表无法查询。 - 事务状态异常:如果你的MySQL隔离级别不是READ UNCOMMITTED,这个大查询会开启一个隐式事务。中断后事务可能没有正确回滚,导致t1表上残留未释放的行锁或事务锁,阻塞后续操作。
3. 重启解决问题的原因
重启MySQL服务器会强制终止所有未完成的事务、释放所有持有的锁、清理所有临时资源,相当于把MySQL的状态重置到初始状态,所以t1表和系统都恢复了正常。
正确的“找不匹配数据”查询方式
如果你想找出两张表中id不匹配的数据,应该用高效的写法,彻底避免笛卡尔积:
-- 找出t1中存在但t2中不存在的id数量 SELECT COUNT(*) FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t2.id = t1.id); -- 或者用LEFT JOIN写法 SELECT COUNT(*) FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL;
这两种写法会利用id上的索引(如果有的话),执行效率会比你原来的写法高几个数量级。
内容的提问来源于stack exchange,提问作者ANIK ISLAM SHOJIB
相关产品推荐
相关产品推荐

