CREATE FUNCTION 报 ERROR 1142 是因未同时授予 CREATE ROUTINE 和 INSERT ON mysql.func 权限;MySQL 8.0.19+ 还要求函数名必须以 udf_ 或 mysql_ 开头。

用户执行 CREATE FUNCTION 报 ERROR 1142,不是权限漏配,而是没给够 CREATE ROUTINE + INSERT 权限组合。
CREATE FUNCTION 被拒绝:必须同时授予 CREATE ROUTINE 和 INSERT
MySQL 在创建 UDF 时,不仅校验函数定义权限,还会往系统表 mysql.func 写入记录(函数名、返回类型、SO 文件路径等)。这意味着:
-
CREATE ROUTINE权限负责允许创建函数语法本身 -
INSERT权限是写入mysql.func表所必需的——缺一不可 - 只给
CREATE ROUTINE会报ERROR 1142 (42000): CREATE FUNCTION command denied - 只给
INSERT在mysql.func上也不行,因为语法层就被拦住了
授权命令必须显式包含两者:
GRANT CREATE ROUTINE, INSERT ON mysql.func TO 'udf_user'@'localhost';
注意:mysql.func 是系统表,不能用通配符 mysql.* 代替;INSERT 权限必须限定在该表上。
UDF 函数名被拒:MySQL 8.0.19+ 强制命名前缀
即使权限和路径都对,CREATE FUNCTION my_hash(...) 在 MySQL 8.0.19 及以上仍会失败,报 ERROR 1125 (HY000): Function 'my_hash' already exists 或更直接的 ERROR 1125: Function name must start with 'udf_' or 'mysql_'。
- 这是硬性 ABI 约束,不是警告——不加前缀就加载失败
- 函数名(不是 SO 文件名,也不是 init 函数名)必须以
udf_或mysql_开头 - 例如合法写法:
CREATE FUNCTION udf_sha256(...) RETURNS STRING ... - 旧版本(8.0.19 前)无此限制,升级后需批量重命名函数定义
普通用户调用 UDF:不需要特殊权限,但受 DEFINER/INVOKER 模式影响
一旦 UDF 成功创建,其他用户能否调用它,取决于函数定义时的 SQL SECURITY 设置和调用者自身权限:
- 默认是
SQL SECURITY DEFINER:函数以定义者身份执行,调用者只需有EXECUTE权限(MySQL 5.7+ 默认授予所有用户) - 若显式设为
SQL SECURITY INVOKER:函数以调用者身份执行,调用者必须拥有函数体内所有 SQL 操作所需的权限(如 SELECT 某表、INSERT 到某日志表等) -
EXECUTE权限本身可被显式收回:REVOKE EXECUTE ON FUNCTION udf_myfunc FROM 'user'@'%';
注意:EXECUTE 权限控制的是“能否调用”,不控制“能否看到函数存在”——函数名仍会出现在 INFORMATION_SCHEMA.ROUTINES 中(除非隐藏元数据)。
权限回收后函数仍能运行?别信,检查 mysql.func 表是否残留
撤销 CREATE ROUTINE 或 INSERT 后,已存在的 UDF 不会自动失效,但以下情况会导致异常:
- 如果后续执行
DROP FUNCTION udf_xxx,需要ALTER ROUTINE权限,否则报错 - 如果函数内部访问了调用者无权访问的表,且是
INVOKER模式,运行时报ERROR 1142 - 最隐蔽的坑:
mysql.func表里残留记录但对应 SO 文件已被删或重命名,下次调用会触发ERROR 1126 (HY000): Can't open shared library,而错误日志里不会提示权限问题,容易误判
排查时优先查:
SELECT * FROM mysql.func WHERE name = 'udf_myfunc';<br>SELECT @@plugin_dir;
确保记录中的 dl 字段值(SO 文件名)真实存在于 plugin_dir 下,且 mysqld 进程可读可执行。











