MySQL小数据量语句执行无响应求助:UPDATE/SELECT长期运行不结束
嘿,我来帮你捋捋这个问题——虽然两张表的数据量都不算大,AWS实例内存也够,但从DROP重建改成TRUNCATE后出现的慢查询,大概率是细节上的差异导致的,给你几个实际的排查步骤:
先查锁!锁!锁!
这是最常见的原因——哪怕数据量小,只要有未提交的事务、锁冲突,语句就会挂起不动。你可以用对应数据库的命令查锁状态:-- 如果你用PostgreSQL: SELECT pid, query, state, locktype, mode FROM pg_locks l JOIN pg_stat_activity s ON l.pid = s.pid WHERE s.datname = '你的数据库名'; -- 如果是MySQL: SHOW ENGINE INNODB STATUS; SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;重点看有没有进程在等待和
mis.pr_approval_time、hj_approval_survey相关的锁,尤其是有没有长时间 idle 的事务占着锁。检查索引和执行计划
DROP重建表的时候会自动重建索引,TRUNCATE只是清数据不碰索引,但如果批量插入数据后索引产生碎片,或者你的UPDATE关联字段没建索引,就会触发全表扫描——哪怕几千行数据,关联逻辑复杂的话也会卡。
先把你说的那个SELECT形式的语句拿去跑执行计划:-- PostgreSQL 用这个能看到实际执行耗时: EXPLAIN ANALYZE 你的SELECT语句; -- MySQL 看执行计划: EXPLAIN 你的SELECT语句;如果看到
Seq Scan(PostgreSQL)或者ALL(MySQL)的扫描类型,说明关联字段没索引,赶紧补上。另外可以手动重建索引优化:-- PostgreSQL REINDEX TABLE mis.pr_approval_time; -- MySQL ALTER TABLE mis.pr_approval_time ENGINE=InnoDB; -- 变相重建索引更新表统计信息
DROP重建表会自动刷新统计信息,但TRUNCATE不会——数据库优化器靠统计信息生成执行计划,过时的统计信息可能会让优化器选到低效方案。手动更新一下:-- PostgreSQL ANALYZE mis.pr_approval_time; ANALYZE hj_approval_survey; -- MySQL ANALYZE TABLE mis.pr_approval_time, hj_approval_survey;排查事务隔离和未提交事务
如果你的数据库用了REPEATABLE READ或者SERIALIZABLE隔离级别,填充数据后有未提交的事务,可能导致UPDATE读取旧快照或者触发锁等待。查一下当前隔离级别和久挂的事务:-- PostgreSQL 查隔离级别: SHOW transaction_isolation; -- 查未提交的长事务: SELECT pid, query, state, xact_start FROM pg_stat_activity WHERE state = 'idle in transaction'; -- MySQL 查隔离级别: SELECT @@transaction_isolation; -- 查长事务: SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;检查AWS实例的实际资源瓶颈
虽然内存有15GB,但要确认数据库真的能用到足够内存(比如PostgreSQL的shared_buffers、MySQL的innodb_buffer_pool_size配置),另外去AWS CloudWatch看一下CPU、磁盘IO的指标——如果是GP2磁盘,IOPS不够的话哪怕小数据量也会卡。
如果能把那个SELECT语句贴出来,我能更精准地帮你定位问题哦!
内容的提问来源于stack exchange,提问作者Shahid Thaika

