创建MySQL函数需要SUPER权限

7

我有一个简单的MySQL函数用于比较版本:

CREATE FUNCTION `compareVersions` (
  versionA VARCHAR(50),
  versionB VARCHAR(50)) RETURNS INT DETERMINISTIC NO SQL
BEGIN
  DECLARE a1 INT;
  DECLARE b1 INT;
   DECLARE c1 INT;
    DECLARE d1 INT;
  DECLARE a2 INT;
  DECLARE b2 INT;
   DECLARE c2 INT;
    DECLARE d2 INT;  SET a1 = SUBSTRING_INDEX( `versionA` , '.', 1 );
  SET b1 = SUBSTRING_INDEX(SUBSTRING_INDEX( `versionA` , '.', 2 ),'.',-1);
  SET c1 = SUBSTRING_INDEX(SUBSTRING_INDEX( `versionA` , '.', -2 ),'.',1);
  SET d1 = SUBSTRING_INDEX( `versionA` , '.', -1 );
  SET a2 = SUBSTRING_INDEX( `versionB` , '.', 1 );
  SET b2 = SUBSTRING_INDEX(SUBSTRING_INDEX( `versionB` , '.', 2 ),'.',-1);
  SET c2 = SUBSTRING_INDEX(SUBSTRING_INDEX( `versionB` , '.', -2 ),'.',1);
  SET d2 = SUBSTRING_INDEX( `versionB` , '.', -1 ); 
  IF (a1 > a2) THEN 
    RETURN -1;
  ELSEIF ((a1 = a2) AND (b1 > b2)) THEN
    RETURN -1;
  ELSEIF ((a1 = a2) AND (b1 = b2) AND (c1 > c2)) THEN
    RETURN -1;
  ELSEIF ((a1 = a2) AND (b1 = b2) AND (c1 = c2) AND (d1 > d2)) THEN
    RETURN -1;
  ELSEIF ((a1 = a2) AND (b1 = b2) AND (c1 = c2) AND (d1 = d2)) THEN  
    RETURN 0;
  ELSE
    RETURN 1;
  END IF;
END $$

创建时出现以下错误:

您没有SUPER权限,并且启用了二进制日志记录(您可能想使用不太安全的log_bin_trust_function_creators变量)

这几乎与此问题相同,但我的函数不读取任何SQL数据,它是简单、确定性的,我看不出为什么它需要任何额外的权限。从文档中我无法确定是否需要SUPER权限才能创建所有函数(这将是荒谬的,使存储函数对许多用户不可用,每个人都无法访问其数据库配置)。我甚至不知道这个函数是否有效,这是我想到的第一件事,但语法应该是正确的(在PHPMyAdmin中设置了分隔符)。可以通过在PHP应用程序中从数据库获取所有数据并进行比较来完成,但我认为这是最容易的方法。这可行吗?有没有更好的解决版本比较的方法?


1
运行此程序的用户是否具有执行权限?(或创建/更改例程的权限) - mable
我不确定,但我想是这样的... 对于 'user'@'localhost' 的 SHOW GRANTS 结果有两行:GRANT USAGE 和 GRANT ALL PRIVILEGES。 - comodoro
截至MySQL 8.0.33版本,似乎这个问题仍然没有得到解决... https://bugs.mysql.com/bug.php?id=110990 我遇到了与原帖作者几乎相同的需求:确定性、无数据库访问、在全局或绑定到数据库创建函数、无需SUPER权限或设置log_bin_trust_function_creators、保持二进制日志记录启用,以ROW格式。我尝试创建这个函数:使用/不使用[user]@[my_ip]作为定义者,将SQL SECURITY设置为INVOKER/DEFINER,将函数与我的用户管理的数据库关联,设置除SUPER权限之外的所有授权但都没有成功... - undefined
2个回答

5
你可以调整全局变量来实现这个功能:
/* allows to create functions as not root */
SET GLOBAL log_bin_trust_function_creators = 1;

我在初始化数据库以恢复转储时使用此方法。


2
我无法更改全局变量,因为我没有根权限。问题部分涉及此事:我是否需要全局根权限来创建存储函数? - comodoro
1
您需要CREATE ROUTINE权限和可选的ALTER ROUTINE权限来创建存储过程。但通常情况下,您应该拥有这些权限。请检查SHOW GRANTS FOR CURRENT_USER();对您显示了什么。 - solick
2
如上所述,我在数据库上拥有GRANT USAGE和GRANT ALL PRIVILEGES。它包括CREATE ROUTINE吗?我想应该是的,但函数创建失败了。 - comodoro
不,这意味着您可以授予不安全的权限并将讲话权限授予其他用户。 - solick
授予权限和授予所有特权本身就是特权。请查看手册:http://dev.mysql.com/doc/refman/5.5/en/grant-table-structure.html - solick
显示剩余2条评论

2
我通过编写冗长且难看的PHP数据库查询来解决了这个问题。也许使用存储过程而不是函数会更好。在搜索后,我在文档这里找到了以下声明:
“MySQL 5.5中有关使用存储函数的当前条件可以总结如下。[...]要创建或更改存储函数,您必须具有SUPER权限,除了通常需要的CREATE ROUTINE或ALTER ROUTINE权限。”
所以,确实,如果二进制日志记录已开启,则确实需要SUPER权限来创建存储函数。这严重限制了在更大的服务器上使用存储函数的能力,并且在我看来降低了整个DBMS的价值。看起来像经典的“这不是一个错误,这是一个特性”。如果在将二进制日志记录更改为开启后重新启动数据库服务器,我担心存储函数会发生什么。

正如我之前提到的,ET GLOBAL log_bin_trust_function_creators = 1; 可以让你在没有 SUPER 权限的情况下创建存储过程和函数。我曾经多次在共享托管系统上创建存储过程和函数,而我没有 root 权限。因此,一个认真的主机商应该已经启用了上述选项。 - solick
1
正如我所提到的,我没有这个权限,并且从错误中可以看出它没有在我使用的系统上设置。我无法对主机提供商做出任何评论,但是所涉及的服务器并未用于托管,如果我是任何数据库服务器的管理员,除非强烈要求,否则我不会隐式设置标记为“潜在不安全”的某些设置。 - comodoro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接