MySQL 5.5+ 中可通过 information_schema.ROUTINES 表查存储过程修改时间,关键字段为 last_altered(需 MySQL 5.7.2+ 才稳定),查询须指定 routine_schema 和 routine_type = 'PROCEDURE',且用户需具备 information_schema 的 SELECT 权限。

直接查 information_schema.ROUTINES 就行,但要注意字段名和权限
MySQL 5.5+ 的 ROUTINES 表里确实有 created 和 last_altered 两个时间字段,last_altered 就是存储过程最后一次被 CREATE PROCEDURE 或 ALTER PROCEDURE 修改的时间。但注意:last_altered 不会因 DROP + CREATE 而重置(只要 routine_name 相同,它就沿用原值),而真正“重建”后时间会被覆盖。
- 必须有对
information_schema的SELECT权限,普通只读账号可能查不到 -
routine_schema是数据库名,不是当前USE的库 —— 即使你USE mydb,也得显式写WHERE routine_schema = 'mydb' -
routine_type = 'PROCEDURE'必须加,否则会混入函数('FUNCTION')结果
last_altered 字段不准?先确认 MySQL 版本和 binlog 格式
last_altered 在 MySQL 5.7.2 及之后才稳定可靠;5.6 及更早版本中,该字段可能始终等于 created,或在某些复制场景下不更新。另外,如果开启了 binlog_format = STATEMENT 且过程内含非确定性语句(如 NOW()、UUID()),ALTER PROCEDURE 可能被跳过记录,导致 last_altered 滞后。
- 检查版本:
SELECT VERSION(); - 检查格式:
SHOW VARIABLES LIKE 'binlog_format'; - 若版本 last_altered,改用
mysqldump --no-data --routines配合 git diff 做人工比对
只想查某一个存储过程?WHERE 条件要精确匹配 routine_name
不要用 LIKE 模糊查,routine_name 是区分大小写的(取决于系统变量 lower_case_table_names),且不带数据库前缀。例如 mydb.get_user 在 ROUTINES 表里只存为 get_user。
- 正确写法:
WHERE routine_schema = 'mydb' AND routine_name = 'get_user' - 错误写法:
WHERE routine_name LIKE '%get%'(可能命中多个,且大小写敏感失效) - 若不确定名字是否含下划线或大小写,先查全量:
SELECT routine_name FROM information_schema.ROUTINES WHERE routine_schema = 'mydb' AND routine_type = 'PROCEDURE';
查不到修改时间?可能是存储过程被 CREATE OR REPLACE 替换过
MySQL 不支持标准 SQL 的 CREATE OR REPLACE PROCEDURE(直到 8.0.30 才实验性支持)。多数人用的是先 DROP 再 CREATE,这会导致 last_altered 变成新时间 —— 看起来像“刚改的”,但实际逻辑可能没变。此时 last_altered 只反映物理重建时间,不代表逻辑变更。
- 验证方式:用
SHOW CREATE PROCEDURE get_user\G对比两次输出的Create Procedure字段内容 - 长期建议:把存储过程定义纳入版本控制,每次
CREATE前生成 SHA256 校验和并记录到元数据表 - 临时补救:
SELECT routine_definition FROM information_schema.ROUTINES WHERE ...可提取源码,但注意该字段被截断(默认最大 64KB,由max_allowed_packet控制)
last_altered 是个弱信号 —— 它只告诉你“这个对象最后什么时候被 DDL 触碰过”,不保证内容真变了,也不记录谁改的、为什么改。需要审计级追踪,得靠触发器 + 日志表,或者开启 general_log(性能代价大)。


















