MVC应用连接MySQL时部分SQL查询报「定义者用户不存在」错误求助
可能的原因
执行的SQL调用了带有
DEFINER属性的数据库对象
报错的SQL大概率调用了视图、存储过程、函数或触发器这类数据库对象,这些对象在创建时被指定了DEFINER='mysqladmin'@'%'。MySQL执行这类对象时,会验证DEFINER指定的用户是否存在——这和你应用的连接用户无关,完全由对象本身的属性触发检查。数据库迁移/导入遗留的配置
如果近期做过数据库备份恢复、或从其他环境导入过数据/对象,这些导入的对象可能携带了原环境的DEFINER配置(比如原环境存在mysqladmin用户),但当前环境没有这个用户,就会触发报错。触发器间接触发了带问题
DEFINER的操作
你的SQL本身可能只是操作普通表,但该表关联的触发器在执行时调用了带有mysqladmin作为DEFINER的对象,或者触发器自身的DEFINER就是mysqladmin,从而引发错误。
排查与解决步骤
定位问题对象
找到报错的那条SQL,确认它是否调用了视图、存储过程等对象。然后用以下SQL查询对象的DEFINER:- 视图:
SHOW CREATE VIEW [视图名]; - 存储过程:
SHOW CREATE PROCEDURE [存储过程名]; - 函数:
SHOW CREATE FUNCTION [函数名]; - 触发器:
SHOW CREATE TRIGGER [触发器名];
查看结果中的DEFINER字段,确认是否为'mysqladmin'@'%'。
- 视图:
修改对象的
DEFINER
将存在问题的对象的DEFINER改为当前环境存在的用户(比如你的连接用户root@localhost):- 修改视图:
ALTER VIEW [视图名] DEFINER = 'root'@'localhost'; - 修改存储过程:
ALTER PROCEDURE [存储过程名] DEFINER = 'root'@'localhost'; - 修改函数:
ALTER FUNCTION [函数名] DEFINER = 'root'@'localhost'; - 修改触发器:
ALTER TRIGGER [触发器名] DEFINER = 'root'@'localhost';
- 修改视图:
临时应急方案(不推荐生产环境)
如果暂时无法修改所有对象的DEFINER,可以临时开启MySQL的skip_name_resolve参数(修改my.cnf/my.ini后重启服务),该参数会跳过MySQL对主机名的解析,从而绕过DEFINER用户存在性检查。但此操作会带来安全风险,仅建议临时排查使用,长期解决方案还是修改对象的DEFINER。
内容的提问来源于stack exchange,提问作者Nielsen

