MySQL UPDATE查询无限挂起,请求协助排查原因
问题根源与解决方案
核心原因:关联字段字符集不匹配导致索引失效
从执行计划能看到两张表都在做全表扫描(type: ALL),尽管你说关联字段建了索引,但索引根本没被用上。看建表语句:
DWH_RAP215的pht字段是utf8字符集TMP_KANNIS038的PHT字段是latin1字符集
字符集不一致时,MySQL无法直接使用索引做关联,只能对两张表做笛卡尔积(570万 × 400万 = 2.28×10¹²条临时数据),这会耗尽服务器资源,导致查询无限挂起。
具体解决步骤
1. 统一关联字段的字符集
优先修改临时表TMP_KANNIS038的字符集,和主表保持一致:
-- 修改字段字符集 ALTER TABLE DWH_RAP215.TMP_KANNIS038 MODIFY COLUMN `PHT` varchar(17) CHARACTER SET utf8 DEFAULT NULL; -- 重新建立索引(确保索引生效) DROP INDEX IDX1 ON DWH_RAP215.TMP_KANNIS038; CREATE INDEX IDX1 ON DWH_RAP215.TMP_KANNIS038(`PHT`);
如果无法修改临时表,也可以在关联时强制转换字符集(但性能略差):
UPDATE DWH_RAP215.`DWH_RAP215` a LEFT JOIN DWH_RAP215.`TMP_KANNIS038` b ON a.`pht` = CONVERT(b.`PHT` USING utf8) SET a.`Vectoring_indication` = b.`Vectoring_indication`;
2. 优化UPDATE语句(可选,针对大表)
对于百万级大表,一次性更新可能导致锁表或资源占用过高,可以分批更新:
-- 每次更新10000条,直到全部完成 SET @row_count = 1; WHILE @row_count > 0 DO UPDATE DWH_RAP215.`DWH_RAP215` a INNER JOIN DWH_RAP215.`TMP_KANNIS038` b ON a.`pht` = b.`PHT` SET a.`Vectoring_indication` = b.`Vectoring_indication` WHERE a.`Vectoring_indication` IS NULL -- 只更新未处理的行 LIMIT 10000; SET @row_count = ROW_COUNT(); END WHILE;
3. 验证索引生效
修改后重新查看执行计划,确认type列显示为ref或range,而非ALL:
EXPLAIN UPDATE DWH_RAP215.`DWH_RAP215` a LEFT JOIN DWH_RAP215.`TMP_KANNIS038` b ON a.`pht` = b.`PHT` SET a.`Vectoring_indication` = b.`Vectoring_indication`;
补充说明
从InnoDB监控信息来看,当前没有I/O等待或锁冲突,说明查询卡在了内存计算笛卡尔积的阶段,这是全表扫描关联的典型表现。解决字符集问题后,索引会被正常使用,关联效率会提升几个数量级。
内容的提问来源于stack exchange,提问作者Bugar Marian
相关产品推荐
相关产品推荐

