DEFINER 和 INVOKER 与长连接无关,权限由 SQL SECURITY 属性及 DEFINER 账户决定;常见错误是 DEFINER host 不匹配导致 1449 错误,修复需重建过程并确保 DEFINER 账户存在且权限完备。

DEFINER 和 INVOKER 不是长连接的配置项,MySQL 存储过程里压根没有“长连接权限”这个概念。所谓“长连接”只是客户端与 MySQL 服务器维持的一个 TCP 连接状态,它本身不携带权限,也不影响存储过程的执行权限逻辑。真正决定权限行为的,只有创建时指定的 SQL SECURITY 属性和对应的 DEFINER 账户。
为什么你看到“长连接下权限失效”,其实是 DEFINER host 匹配失败
常见错误现象:ERROR 1449 (HY000): The user specified as a definer ('admin'@'%') does not exist 或者明明能连上、也能 CALL,但一查表就报 Access denied。
根本原因不是连接时长,而是:MySQL 在执行 DEFINER 模式时,会严格按 'user'@'host' 全匹配查找该账户——而这个 host 是创建时固化下来的,和当前连接用的 host 无关。
- 比如你用
admin@localhost创建了过程,但应用是通过远程 IP(如10.20.30.40)连进来的,那么admin@%必须存在且有权限;admin@localhost即使存在也匹配不上 - 反过来,如果过程
DEFINER是admin@%,但该账号在 mysql.user 表里只定义了admin@10.20.30.%,照样报 1449 -
CURRENT_USER()返回的是认证时的'user'@'host',而USER()返回带客户端 IP 的完整标识,二者在代理或跳板场景下可能不同,但DEFINER只认前者
SQL SECURITY INVOKER 才是真·按调用者权限走,但别漏掉动态 SQL
想让存储过程完全遵循调用者的权限边界,必须显式声明 SQL SECURITY INVOKER。默认是 DEFINER,不写就等于写了 DEFINER。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 创建时必须写全:
CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER PROCEDURE proc_name...,只写SQL SECURITY INVOKER不够,MySQL 5.7+ 仍可能补默认DEFINER - 调用时每条静态 SQL 都实时校验调用者权限(比如
SELECT FROM log_table→ 检查调用者是否有log_table的SELECT权) - 但一旦用了
PREPARE+EXECUTE动态拼表名或库名,那这部分 SQL 就退回到INVOKER规则——即仍查调用者权限,不会因为过程是DEFINER就豁免 - 所以如果过程里有
SET @sql = CONCAT('SELECT * FROM ', db_name, '.events');,那db_name对应的库和表,调用者都得有对应权限
修复已存在的 DEFINER 错误不能靠 ALTER PROCEDURE ... DEFINER=
MySQL 8.0.16 之前根本不支持直接改 DEFINER;8.0.16+ 虽支持,但需要 SET_USER_ID 权限(普通 DBA 通常没有),且操作后不自动刷新权限缓存。
- 稳妥做法永远是重建:
SHOW CREATE PROCEDURE proc_name拿到完整 DDL - 把开头的
DEFINER=`old`@`host`替换成新账号,例如DEFINER=`proc_runner`@`%` - 确保新
DEFINER账号真实存在,并被授予过程内所有静态语句涉及的库/表/列权限(注意:不是 EXECUTE 权限!) - 执行新 DDL 创建过程,再
DROP PROCEDURE old_proc_name(别忘了先确认依赖)
关键点其实就一个:权限不绑定连接时长,而绑定 DEFINER 账户是否存在、是否可匹配、是否真有对应对象权限。很多人卡在“连得上却跑不动”,问题从来不在连接本身,而在创建过程那一行 DEFINER 写得太随意。










