mysql函数权限如何设置_mysql安全配置方法

来源:这里教程网 时间:2026-02-28 20:47:31 作者:

MySQL 函数创建权限到底要哪些?

普通用户执行

CREATE FUNCTION
会直接报错:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration
,但这只是表象。真正卡住的是权限和全局配置双重限制。

必须同时满足:

用户拥有
CREATE ROUTINE
权限(不是
CREATE FUNCTION
—— 这个权限不存在)
用户拥有
ALTER ROUTINE
权限(后续修改函数需要)
MySQL 启动时未设置
--log-bin
,或已显式设置
log_bin_trust_function_creators=1

否则即使权限全开,也会因二进制日志安全机制被拒绝。

如何安全开启自定义函数支持?

不建议直接设

log_bin_trust_function_creators=1
后全局放行。更稳妥的做法是:

仅在确需函数复制的主从环境中启用该参数,且只对可信账号授权
my.cnf
中添加:
[mysqld]
log_bin_trust_function_creators = ON
修改后必须重启 MySQL(动态 SET 不生效) 随后授予具体用户权限:

GRANT CREATE ROUTINE, ALTER ROUTINE ON *.* TO 'dev_user'@'localhost';

注意:

ON <em>.</em>
是全局级别;若只需某库,用
ON <code>app_db
.* 即可,但函数本身仍可跨库调用。

函数体里访问数据表,权限怎么算?

函数运行时的权限,取决于定义者(DEFINER) 而非调用者(INVOKER),这是关键误区。

若定义为
DEFINER = 'admin'@'%'
,则函数内所有
SELECT/INSERT
操作都以
admin
权限执行
若定义为
SQL SECURITY INVOKER
,则权限检查发生在调用时刻,依赖当前用户对目标表的权限

生产环境强烈建议显式声明:

CREATE FUNCTION get_user_name(uid INT) RETURNS VARCHAR(50) READS SQL DATA SQL SECURITY DEFINER ...

否则默认是

DEFINER
,但若定义者账号后来被删或密码过期,函数会直接失效,且错误提示极不直观(常表现为空结果或
NULL
)。

为什么函数在命令行能跑,Java 应用却报错?

常见于 JDBC 连接串未指定

allowMultiQueries=true
或未关闭 prepared statement 缓存,但更隐蔽的原因是:

MySQL 8.0+ 默认禁用
CREATE FUNCTION
的自动权限继承
应用连接使用的账号可能没被显式授予
CREATE ROUTINE
,即使它是
root
降权后的账号
函数中用了
SELECT ... INTO
但目标变量未声明,错误被 JDBC 吞掉,只返回空结果

排查时先在 MySQL 客户端用同一账号执行:

SHOW GRANTS FOR CURRENT_USER;

确认输出中包含
CREATE ROUTINE
;再检查函数体内所有表名是否带库名前缀(避免跨库时因权限粒度问题失败)。

函数权限的复杂性不在授权动作本身,而在于定义者语义、二进制日志策略、以及调用上下文的三重耦合。漏掉任意一环,都会表现为“明明给了权限却不能用”。

相关推荐