改主机名会导致definer失效,因mysql权限校验依赖'user'@'host'完整二元组;host变更后原definer账号在mysql.user中不复存在,执行时直接报error 1449,连权限检查环节都无法进入。

改主机名本身不会删权限,但会直接让所有 DEFINER 失效——因为 MySQL 权限系统认的是 'user'@'host' 这个完整二元组,host 一变,原来定义的存储过程、函数、触发器就全找不到“爹”了。
为什么 SHOW GRANTS 还显示有权限,但调用就报 ERROR 1449?
这是最典型的症状:你查 SHOW GRANTS FOR 'app_user'@'old-hostname' 没问题,但执行过程时却崩在 ERROR 1449: The user specified as a definer ('app_user'@'old-hostname') does not exist。原因很直白:
- 存储过程创建时写的
DEFINER='app_user'@'old-hostname'是硬编码进mysql.proc表的,不是运行时动态解析的 - 主机名改了(比如从
db01改成db-prod),'app_user'@'old-hostname'这个账户在mysql.user里就彻底不存在了 - MySQL 在执行时严格校验 DEFINER 是否存在且可登录,不匹配就立刻拒绝,连权限检查环节都进不去
别去 UPDATE mysql.proc —— 8.0+ 已禁止且字段语义变了
MySQL 8.0+ 把过程元数据移到数据字典,mysql.proc 表已只读或废弃。即使你强行写进去,也会遇到:
-
definer字段类型是TEXT,但内部有格式校验,乱填会触发ERROR 1418 - 修改后不触发权限重载,必须
DROP + CREATE才生效 - 如果过程用了
SQL SECURITY DEFINER,你还得同步确保新 host 上的同名用户真有对应表权限
安全重建流程:导出 → 替换 → 删除 → 重创建
必须走逻辑重建,不能碰底层表。三步闭环操作:
- 导出时强制替换 DEFINER:
mysqldump -u root -p --skip-definer --routines dbname > routines.sql(--skip-definer会让 dump 文件里所有 DEFINER 变成CURRENT_USER) - 若已导入失败,用 sed 清洗已有 SQL:
sed -i "s/DEFINER=`[^`]*`@`[^`]*`/DEFINER=CURRENT_USER/g" routines.sql - 先
DROP PROCEDURE IF EXISTS p1;,再 source 新 SQL;不要跳过 DROP,否则CREATE OR REPLACE在部分版本下不更新 DEFINER
最容易被忽略的点:host 匹配规则和认证插件双杀
就算你把 DEFINER 改成 CURRENT_USER,如果当前连接用的是 'app_user'@'localhost',而该用户实际只在 mysql.user 里存了 'app_user'@'127.0.0.1',那 CURRENT_USER() 返回的仍是空值,过程还是跑不起来。更麻烦的是,MySQL 8.0 默认 caching_sha2_password 插件,旧客户端连上来可能认证成功但 CURRENT_USER() 拿不到真实 host——建议在重建前先确认:SELECT User, Host, plugin FROM mysql.user WHERE User = 'app_user';











