在声明中使用DETERMINISTIC,NO SQL或READS SQL DATA并启用二进制日志记录


107

在mysql中导入数据库时​​,出现以下错误:

1418 (HY000) at line 10185: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

我不知道我需要改变什么。谁能帮我解决这个问题?

Answers:


236

有两种方法可以解决此问题:

  1. 在MySQL控制台中执行以下命令:

    SET GLOBAL log_bin_trust_function_creators = 1;

  2. 将以下内容添加到mysql.ini配置文件中:

    log_bin_trust_function_creators = 1;

该设置放宽了对不确定功能的检查。非确定性函数是修改数据(即具有更新,插入或删除语句)的函数。有关更多信息,请参见此处

请注意,如果未启用二进制日志记录,则此设置不适用。

存储程序的二进制记录

如果未启用二进制日志记录,则log_bin_trust_function_creators不适用。

log_bin_trust_function_creators

启用二进制日志记录时,此变量适用。

最好的方法是更好地理解和使用存储函数的确定性声明。MySQL使用这些声明来优化复制,并且仔细选择它们以确保复制正常是一件好事。

确定性 如果例程对于相同的输入参数总是产生相同的结果,则例程被认为是“确定性”,否则,则不是“确定性”。这主要用于字符串或数学处理,但不仅限于此。

非确定性 与“确定性”相反。“ 如果例程定义中未给出DETERMINISTIC或NOT DETERMINISTIC,则默认值为NOT DETERMINISTIC。要声明函数是确定性的,必须显式指定DETERMINISTIC。 ” 因此,如果没有声明,MySQl似乎会将函数视为“ NOT DETERMINISTIC”。手册中的这一陈述与手册另一领域的其他陈述相抵触:创建存储函数时,必须声明它是确定性的或未修改数据。否则,对于数据恢复或复制可能是不安全的。默认情况下,要接受CREATE FUNCTION语句,必须显式指定DETERMINISTIC,NO SQL或READS SQL DATA中的至少一项。否则会发生错误

如果没有声明,我个人会在MySQL 5.5中出错,所以无论我可能有其他声明如何,我总是至少放置一个声明“ DETERMINISTIC”,“ NOT DETERMINISTIC”,“ NO SQL”或“ READS SQL DATA”。

READS SQL DATA 这明确地告诉MySQL该函数将仅从数据库中读取数据,因此,它不包含修改数据的指令,但包含读取数据的SQL指令(即SELECT)。

MODIFIES SQL DATA 这表明例程包含可能写入数据的语句(例如,它包含UPDATE,INSERT,DELETE或ALTER指令)。

NO SQL 这表明该例程不包含SQL语句。

CONTAINS SQL 这表示该例程包含SQL指令,但不包含读取或写入数据的语句。如果未明确给出这些特征,则为默认设置。此类语句的示例为SELECT NOW(),SELECT 10 + @ b,SET @x = 1或DO RELEASE_LOCK('abc'),它们执行但既不读取也不写入数据。

请注意,有些MySQL函数不是确定性安全的,例如:NOW(),UUID()等,它们可能在不同的机器上产生不同的结果,因此包含此类指令的用户函数必须声明为NOT DETERMINISTIC 。同样,从非复制模式中读取数据的函数显然是NONDETERMINISTIC。*

例程性质的评估基于创建者的“诚实”:MySQL不检查声明为DETERMINISTIC的例程是否没有产生不确定结果的语句。但是,错误声明例程可能会影响结果或影响性能。将不确定性例程声明为DETERMINISTIC可能会导致优化器做出错误的执行计划选择,从而导致意外结果。将确定性例程声明为NONDETERMINISTIC可能会导致不使用可用的优化,从而降低性能。


你能解释一下背景发生了什么吗?
ASR 2014年

2
我怀疑数据库具有修改数据的功能(其中具有更新,插入或删除语句)。有关更多信息,请参见此处:dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html
Donal

1
您应该始终备份
Donal

它需要超级特权!
菲利佩·莫拉莱斯

尝试过这个,但仍然有不确定的问题,还有其他建议吗?谢谢
Edwin Bermejo '18

40
  • 创建存储函数时,必须声明它是确定性的或未修改数据。否则,对于数据恢复或复制可能是不安全的。

  • 默认情况下,要接受CREATE FUNCTION语句,必须显式指定DETERMINISTIC,NO SQL或READS SQL DATA中的至少一项。否则会发生错误:

要解决此问题,请在“ Return”之后和“ Begin Begin”语句之前添加以下行:

READS SQL DATA
DETERMINISTIC

例如 :

CREATE FUNCTION f2()
RETURNS CHAR(36) CHARACTER SET utf8
/*ADD HERE */
READS SQL DATA
DETERMINISTIC
BEGIN

有关此问题的更多详细信息,请阅读此处


之所以起作用,是因为该设置READS SQL DATA对这三个设置的限制最少。如果您的函数属于NO SQLDETERMINISTIC类别,则可以通过修改函数来提高性能。另一方面,该设置READS SQL DATA也最不容易出错。因此,如果您使用不正确,NO SQL否则DETERMINISTIC可能会得到不正确的结果。
乔纳森

@ SunnyS.M,很棒的解释,例如READS SQL DATA DETERMINISTIC。要解决此问题,请在“ Return”和“ Begin Begin”语句之前添加以下行:
Md Haidar Ali Khan,

4

在唐纳德发表评论之后:

启用二进制日志记录时,此变量适用。

我要做的就是:

  1. 在my.cnf(#log_bin)中禁用了log_bin
  2. 重启mysql
  3. 导入数据库
  4. 启用log_bin
  5. 重启mysql

那解决了导入问题。

(然后,我将审查程序员的代码以提出改进建议)


3

当您的函数是确定性的时,您可以放心地将其声明为确定性的。“ DETERMINISTIC”关键字的位置如下。

在此处输入图片说明


2

在Windows 10上,

我只是通过执行以下操作解决了这个问题。

  1. 转到my.ini,并在[mysqld]下添加这两行

    skip-log-bin
    log_bin_trust_function_creators = 1
    
  2. 重启MySQL服务


完成此操作后,我在奴隶上出现了错误Got fatal error 1236 from master when reading data from binary log: 'Binary log is not open'
Ramratan Gupta

0

尝试设置函数的定义器!

所以代替

CREATE FUNCTION get_pet_owner

你会写一些类似于

CREATE DEFINER=procadmin@% FUNCTION get_pet_owner

如果用户prodacmin有权创建功能/程序,则该方法应该起作用。

就我而言,该函数在通过MySQL Workbench生成时起作用,但在直接作为SQL脚本运行时却不起作用。进行以上更改可以解决问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.