函数丢失主因是升级时mysql.proc表迁移失败导致元数据丢失,而非log_bin_trust_function_creators配置;应先查information_schema.ROUTINES确认是否存在,再据备份或旧实例恢复。

函数丢失不是因为 log_bin_trust_function_creators
这个配置项只影响「创建函数时是否报错」,和升级后函数消失完全无关。它控制的是:当 log_bin 开启且函数有非确定性行为(比如 NOW()、UUID())时,MySQL 是否允许你 CREATE FUNCTION。设为 OFF 会直接拒绝创建;设为 ON 才能建成功。但它不存储、不管理已存在的函数元数据。
先确认函数到底还在不在
别急着改配置或重装。直接查 information_schema.ROUTINES:
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys');
如果结果为空,说明函数记录确实从数据字典里消失了——这不是权限或配置问题,是元数据丢失。
函数消失的真正原因通常是升级过程破坏了 mysql.proc 表
MySQL 5.7 及以前,函数/存储过程定义存在 mysql.proc 表里;8.0 改用数据字典表(mysql.routines 等),升级时需执行 mysql_upgrade 或等 mysqld 自动迁移。但以下情况会导致迁移失败:
- 升级前
mysql.proc表本身已损坏(如被手动 TRUNCATE、字段乱序) - 升级过程中 mysqld 被强制终止,迁移中途退出
- 使用了自定义
my.cnf,禁用了skip-grant-tables但没配好权限校验,导致系统表初始化卡住 - 从极老版本(如 5.5)跨大版本升级,未走中间版本过渡
此时 mysql.proc 文件可能还躺在 datadir 下,但 8.0 的 server 已经不读它了。
恢复函数最可行的三步路径
前提是:你有升级前的备份,或者还能连上旧实例。
- 如果有
mysqldump --routines备份:直接用mysql -u root -p db_name 导入(注意加 <code>--default-character-set=utf8mb4) - 如果旧实例还能访问:在旧库上执行
SHOW CREATE FUNCTION func_name,复制出完整语句,在新库上重新执行(记得先设log_bin_trust_function_creators = ON再 CREATE) - 如果只有
datadir/mysql/proc.MYD和.MYI文件:停掉 MySQL,用 5.7 的 mysqld 临时启动该 datadir,导出函数定义,再切回 8.0 执行。不要试图把 .MYD 文件直接拷进 8.0 的 data 目录——引擎和结构已不兼容
最后提醒一句:函数定义一旦从数据字典里清空,就无法靠 ibd2sql 或 ALTER TABLE ... IMPORT TABLESPACE 恢复。它们只管数据页,不管 routine 元数据。真正容易被忽略的,是升级前没做 mysqldump --all-databases --routines --triggers 全量逻辑备份——这比任何配置修复都管用。


















