当前位置:首页 > 问答 > 正文

Oracle MySQL里那些动态表怎么搞,实际操作中遇到的问题和解决思路分享

说到Oracle MySQL里的动态表,其实我们平时说的“动态表”并不是一个专门的表类型,它更多指的是那些内容会随着数据库运行而自动变化的数据表,主要就是信息模式(INFORMATION_SCHEMA) 下的表和性能模式(PERFORMANCE_SCHEMA) 下的表,这些表不是用来存我们自己的业务数据的,而是MySQL自己用来告诉你数据库内部正在发生什么的“监控大屏”。(来源:MySQL官方文档关于INFORMATION_SCHEMA和PERFORMANCE_SCHEMA的概述)

这些动态表能用来干嘛?实操场景举例

我刚接触的时候,也觉得这些表很神秘,但用熟了发现简直是排查问题的神器。

  1. 查表结构,批量生成SQL脚本:有一次,我们需要给几十张表统一增加一个审计字段,手动改太蠢了,我就用了 INFORMATION_SCHEMA.COLUMNS 这个表,我先用查询语句看看这些表是否已经存在这个字段,避免重复添加。

    -- 检查特定数据库下,所有表是否含有 'audit_user' 这个字段
    SELECT TABLE_NAME
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = 'my_database' AND COLUMN_NAME = 'audit_user';

    确认没有后,再写一个查询,动态生成所有的 ALTER TABLE 语句:

    -- 生成添加字段的SQL语句
    SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' ADD COLUMN audit_user VARCHAR(50) NULL COMMENT \"审核人\";') AS ddl_sql
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = 'my_database' AND TABLE_TYPE = 'BASE TABLE';

    然后把生成的结果复制出来直接执行,一分钟搞定所有表,非常高效。(来源:基于INFORMATION_SCHEMA.TABLES和COLUMNS表的常见用法)

  2. 排查锁等待,解决“卡死”问题:线上环境偶尔会有操作卡住,提示锁超时,这时候 INFORMATION_SCHEMA.INNODB_LOCKSINNODB_LOCK_WAITS(在MySQL 5.7中)或者 PERFORMANCE_SCHEMA 中的相关表(在MySQL 8.0中更推荐)就派上用场了。 有一次,一个简单的UPDATE语句一直不返回,我立刻连上数据库,查询锁等待情况:

    -- 在MySQL 5.7环境中查看当前锁等待
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

    这个查询会告诉你哪个事务(blocking_trx_id)阻塞了另一个事务(waiting_trx_id),然后我再根据事务ID去 INFORMATION_SCHEMA.INNODB_TRX 表里查具体的SQL语句和连接信息,很快就定位到是一个未提交的长事务占着锁不放,通知对应的开发人员提交事务后,问题立马解决。(来源:MySQL官方文档关于InnoDB锁事务的监控)

  3. 监控性能瓶颈PERFORMANCE_SCHEMA 更强大,但也更复杂,它像是一个内置的APM工具,我们曾经遇到数据库偶尔CPU飙升的问题,在业务高峰时,我通过查询 PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_DIGEST 表,找到了那些执行次数最多、平均耗时最长的SQL摘要。 这个表的好处是,它会把结构相同但参数不同的SQL归为一类(通过digest),让你一眼看出哪类SQL是性能瓶颈,然后我再根据摘要信息,去慢查询日志或者应用日志里找具体的SQL进行优化,比如加索引或者改写SQL。(来源:MySQL官方文档关于使用PS进行语句摘要分析)

实际操作中遇到的坑和解决思路

用这些动态表也不是一帆风顺的,有几个常见的坑。

  1. 版本差异巨大,语法说变就变:这是最大的坑,比如上面说的锁等待查询,在MySQL 5.7里主要用 INFORMATION_SCHEMA 下的表,但到了MySQL 8.0,官方更推荐使用 PERFORMANCE_SCHEMA 下的 data_locksdata_lock_waits 表,如果你照着老版本的教程去新版本里查,肯定会报错“表不存在”。

    • 解决思路:在尝试之前,一定要先 SELECT VERSION(); 看清楚数据库版本,然后去查阅对应版本的官方手册,官方手册是唯一可靠的标准。
  2. 数据量巨大,查询可能影响性能PERFORMANCE_SCHEMA 的一些表会记录非常细粒度的性能数据,如果开启了很多监控项,这些表本身的数据量会增长得很快,如果你写了一个不加条件的全表扫描查询,可能会适得其反,消耗大量资源,甚至把自己卡死。

    • 解决思路:查询时一定要有针对性,尽量带上 WHERE 条件,比如限制时间范围、特定的数据库名、表名或线程ID,不是所有监控项都需要开启,可以根据实际需求,在MySQL配置文件中调整 performance_schema 的配置,只开启必要的监控器,减少开销。
  3. 数据是动态的,瞬间即逝:这些表里的数据大多是内存中的实时状态,一旦查询执行完,或者服务器重启,数据就没了,你很难像业务数据一样去回溯历史问题,比如你想分析一个小时前的锁冲突,如果当时没查,过后就查不到了。

    • 解决思路:对于需要长期监控和分析的关键指标,不能只依赖手动查询,需要搭建外部的监控系统(如Prometheus+Grafana、Zabbix等),定期(比如每秒)采集 PERFORMANCE_SCHEMAsys schema(一个基于PS的视图库,让查询更简单)中的数据,持久化存储起来,这样才能做趋势分析和告警。
  4. 理解成本高,字段含义晦涩:像 PERFORMANCE_SCHEMA 里的表,很多字段名非常底层,TIMER_STARTNESTING_EVENT_ID 等,如果不理解MySQL内部的计时机制和事件嵌套模型,根本看不懂数据代表什么意思。

    • 解决思路:对于初学者,建议先从 INFORMATION_SCHEMA 用起,它相对直观,当需要深入性能分析时,可以先使用 sys schema。sys schema提供了一系列人类易读的视图、函数和存储过程,它把 PERFORMANCE_SCHEMAINFORMATION_SCHEMA 的复杂数据封装成了像“哪些语句全表扫描了”、“哪个主机占用了最多连接”这样的直观视图,大大降低了使用难度,把它当作一个“傻瓜式”的入口,等熟悉了再深入底层表。

MySQL的这些动态表是DBA和开发人员深入了解数据库内部状态的强大工具,但要用好它们,关键是多动手、多踩坑,并且永远以官方文档为最终依据。

Oracle MySQL里那些动态表怎么搞,实际操作中遇到的问题和解决思路分享