查存储过程必须用 INFORMATION_SCHEMA.ROUTINES,它是MySQL 5.7–8.4唯一兼容的标准路径,需加 ROUTINE_TYPE = 'PROCEDURE' 过滤并指定 ROUTINE_SCHEMA,推荐按 CREATED DESC 排序。

查存储过程必须用 INFORMATION_SCHEMA.ROUTINES
MySQL 不像 PostgreSQL 有 \df 这类快捷命令,所有元数据都得从系统库查。直接查 mysql.proc 表在 8.0+ 已废弃且权限受限,INFORMATION_SCHEMA.ROUTINES 是唯一兼容 5.7–8.4 的标准路径。
注意:该视图默认只返回当前用户有 EXECUTE 权限的存储过程,哪怕你是 root,如果没显式授权给某个数据库下的 routine,它也不会出现。
-
ROUTINE_SCHEMA字段对应数据库名,筛选时必须用= DATABASE()或明确写库名,不能依赖SCHEMA()函数(它不总等于当前 USE 的库) - 只查存储过程别漏掉
AND ROUTINE_TYPE = 'PROCEDURE',否则函数(FUNCTION)也会混进来 - 排序建议加
ORDER BY CREATED DESC,新创建的排前面,比按名字排实用得多
最简可用的一行查询语句
不用记复杂字段,日常够用的就这句:
SELECT ROUTINE_NAME, CREATED, LAST_ALTERED FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE() AND ROUTINE_TYPE = 'PROCEDURE' ORDER BY CREATED DESC;
如果想看完整定义(比如调试时需要确认参数),把 ROUTINE_DEFINITION 加进 SELECT;但要注意:ROUTINE_DEFINITION 在 definer 权限不足或开启了 log_bin_trust_function_creators=OFF 时会显示为 NULL。
- 别用
SHOW PROCEDURE STATUS替代——它不返回创建时间、不支持 WHERE 过滤、字段名不标准(比如叫Db而不是ROUTINE_SCHEMA) - 如果结果为空,先执行
SELECT DATABASE();确认当前库,再检查SELECT COUNT(*) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'your_db_name' AND ROUTINE_TYPE = 'PROCEDURE';
跨库查或导出全部定义的实操要点
运维或迁移时经常要批量处理多个库的存储过程,这时不能只依赖 DATABASE()。
- 查指定库:把
DATABASE()换成字符串,如ROUTINE_SCHEMA = 'my_app',注意引号不能丢 - 导出定义:用
SELECT CONCAT('CREATE PROCEDURE ', ROUTINE_NAME, ' ', ROUTINE_DEFINITION) FROM ...拼接,但ROUTINE_DEFINITION含换行和注释,直接复制可能语法错误;更稳的方式是用mysqldump --routines --no-create-info --no-data your_db - 权限问题最常卡在这里:即使有 SELECT 权限,若 routine 的
DEFINER是其他用户且你没 SUPER 权限,ROUTINE_DEFINITION仍为空——这不是 bug,是安全限制
为什么 information_schema 查询有时特别慢
尤其是库多、routine 多的实例,首次查 INFORMATION_SCHEMA.ROUTINES 可能卡好几秒。这不是数据量大,而是 MySQL 每次都要实时扫描每个数据库的 .frm 或数据字典表。
- 加
WHERE ROUTINE_SCHEMA = 'xxx'能显著提速,不加的话会遍历所有库 - 8.0+ 开启了原子 DDL,但
INFORMATION_SCHEMA视图本身不走缓存,没法靠 query cache 优化 - 如果只是想确认某个过程是否存在,用
SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'x' AND ROUTINE_NAME = 'y' LIMIT 1比全量查快得多
真正麻烦的是嵌套调用关系——INFORMATION_SCHEMA 不提供依赖分析,要看谁调用了谁,只能 grep 定义文本或者上 pt-show-grants 这类工具。


















