information_schema和performance_schema查询会阻塞dml,因其是动态伪视图,不走索引、无缓存,且在触发器中执行时提前加mdl共享锁,导致alter table等操作等待,引发dml卡顿;应移出写入路径,改由应用层或定时任务预热缓存。

information_schema 和 performance_schema 这类系统视图在高并发下查一次就可能卡住整个 DML 流程,不是因为语句慢,而是它们根本不走索引、不缓存、且会抢元数据锁(MDL)。
information_schema 查询为什么会阻塞 INSERT/UPDATE?
- 它不是物理表,而是每次查询都动态扫描内存结构+校验权限+采集快照的“伪视图”
-
SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_NAME = 'orders'看似只查一张表,实际会加载整个库的列定义缓存 - 在 BEFORE 触发器里执行这句,等于在主事务还没提交前,就对数据字典加共享 MDL 锁;此时若有 ALTER TABLE 正在运行,INSERT 就立刻卡住
-
SHOW ENGINE INNODB STATUS中会显示waiting for table metadata lock,单行插入从 2ms 涨到 800ms 是典型现象
performance_schema 查起来真轻量吗?
- 并不轻。尤其开启
events_statements_history后,每条语句都会写入环形缓冲区 - 触发器里反向查它(比如
SELECT * FROM performance_schema.events_statements_current WHERE THREAD_ID = CONNECTION_ID()),等于在写入高峰期做同步读取 + 解析 - 极易触发 mutex 竞争,
performance_schema的读操作本身也会被其他写操作阻塞
哪些写法会让问题更严重?
- 所有带
WHERE条件的information_schema查询——MySQL 5.7.20 前版本完全不走索引,哪怕WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 't'也是全表扫描 - 在 AFTER 触发器中查
information_schema.TABLES判断表是否存在:不仅慢,还可能因锁等待链引发死锁 - 把
SHOW COLUMNS FROM t包进存储函数再被触发器调用:多一层解析开销,且无法被连接池复用
真正难处理的不是“怎么让 information_schema 查得更快”,而是它根本不该出现在写入路径上。元数据检查必须前置到应用层、预热进本地缓存,或改用异步定时任务拉取并落地成配置表——只要它还在触发器里,就随时可能变成高并发下的静默瓶颈。










