ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQ_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3147 | 回复: 0   主题: ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQ        下一篇 
谁是天蝎
注册用户
等级:大元帅
经验:90210
发帖:106
精华:0
注册:2011-7-21
状态:离线
发送短消息息给谁是天蝎 加好友    发送短消息息给谁是天蝎 发消息
发表于: IP:您无权察看 2015-4-10 16:38:34 | [全部帖] [楼主帖] 楼主

今天创建function

 CREATE FUNCTION `func_get_split_string_total`(f_string varchar(1000),f_delimiter varchar(5)) RETURNS int(11)
BEGIN
return 1+(length(f_string) - length(replace(f_string,f_delimiter,'')));


报错信息:

ERROR 1418 (HY000): 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)


查了一些资料,解决办法是把log_bin_trust_function_creators = 1
但是log_bin_trust_function_creators这个参数是做什么的呢?开启后会有哪些影响呢?
接下来开始介绍一下相关的作用及影响:
对存储子程序语句的二进制日志功能的特征在下面列表中描述。一些条目指出你应该注意到的问题。
CREATE PROCEDURE, CREATE FUNCTION, ALTER PROCEDURE,和ALTER FUNCTION 语句被写进二进制日志,CALL, DROP PROCEDURE, 和DROP FUNCTION 也一样。
尽管如此,对复制有一个安全暗示:要创建一个子程序,用户必须有CREATE ROUTINE权限,但有这个权限的用户不能写一个 子程序在从服务器上执行任何操作。因为在从服务器上的SQL线程用完全权限来运行。例如,如果主服务器和从服务器分别有服务器ID值1和2,在主服务器上的用户可能创建并调用如下一个 程序:

 mysql> delimiter //
mysql> CREATE PROCEDURE mysp ()
-> BEGIN
-> IF @@server_id=2 THEN DROP DATABASE accounting; END IF;
-> END;
-> //
mysql> delimiter ;
mysql> CALL mysp();


CREATE PROCEDURE和CALL语句将被写进二进制日志,所以从服务器将执行它们。因为从SQL线程有完全权限,它将移除accounting数据库。
要使允许二进制日志功能的服务器避免这个危险,MySQL 5.1已经要求 存储程序和函数的创建者除了通常需要的CREATE ROUTINE的权限外,还必须有SUPER 权限。类似地,要使用ALTER PROCEDURE或ALTER FUNCTION,除了ALTER ROUTINE权限外你必须有SUPER权限。没有SUPER权限,将会发生一个错误:

ERROR 1419 (HY000): You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)


你可能不想强制要求子程序创建者必须有SUPER权限。例如,你系统上所有有CREATE ROUTINE权限的用户可能是有经验的应用程序开发者。要禁止掉对SUPER权限的要求,设置log_bin_trust_routine_creators 全局系统变量为1。默认地,这个变量值为0。
如果二进制日志功能不被允许,log_bin_trust_routine_creators 没有被用上,子程序创建需要SUPER权限。
i. 一个执行更新的非确定子程序是不可重复的,它能有两个不如意的影响:
ii.它会使得从服务器不同于主服务器。
iii.恢复的数据与原始数据不同。
要解决这些问题,MySQL强制做下面要求:在主服务器上,除非子程序被声明为确定性的或者不更改数据,否则创建或者替换子程序将被拒绝。这意味着当你创建一个子程序的时候,你必须要么声明它是确定性的,要么它不改变数据。两套子程序特征在这里适用:
i.DETERMINISTIC和NOT DETERMINISTIC指出一个子程序是否对给定的输入总是产生同样的结果。如果没有给定任一特征,默认是NOTDETERMINISTIC,所以你必须明确指定DETERMINISTIC来 声明一个 子程序是确定性的。
ii. 使用NOW() 函数(或它的同义)或者RAND() 函数不是必要地使也一个子程序非确定性。对NOW()而言,二进制日志包括时间戳并正确复制。RAND()只要在一个 子程序内被调用一次也可以正确复制。(你可以认为子程序执行时间戳和随机数种子作为毫无疑问地输入,它们在主服务器和从服务器上是一样的。)
iii.CONTAINS SQL, NO SQL, READS SQL DATA, 和 MODIFIES SQL数据提供子程序是读还是写数据的信息。无论NO SQL 还是READS SQL DATA 都指出,子程序没有改变数据,但你必须明白地指明这些中的一个,因为如果任何这些特征没有被给出, 默认的特征是CONTAINS SQL。
当你开启binlog,要一个 CREATE PROCEDURE 或 CREATE FUNCTION 语句被接受,DETERMINISTIC 或 NO SQL与READS SQL DATA 中的一个必须明白地指定,否则会产生如下错误:

ERROR 1418 (HY000): This routine 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_routine_creators variable)。


注意,子程序本性的评估是基于创建者的“诚实度” :MySQL不检查声明为确定性的子程序是否不含产生非确定性结果的语句。
如果子程序返回无错,CALL语句被写进二进制日志,否则就不写。当一个子程序修改数据失败了,你会得到这样的警告:

ERROR 1417 (HY000): A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes.


这个记日志行为潜在地导致问题.如果一个子程序部分地修改一个非交互表(比如一个MyISAM表able)并且返回一个错误,二进制日志将反映这些变化。要防止这种情况,你应该在 子程序中使用交互表并且在交互动作内修改表。
在一个子程序内,如果你在INSERT, DELETE, 或者UPDATE里使用IGNORE关键词来忽略错误,可能发生一个部分更新,但没有错误产生。这样的语句被记录日志,且正常复制。
如果一个存储函数在一个如SELECT这样不修改数据的语句内被调用,即使函数本身更改数据,函数的执行也将不被写进二进制日志里。这个记录日志的行为潜在地导致问题。假设函数myfunc()如下定义:

 CREATE FUNCTION myfunc () RETURNS INT
BEGIN
INSERT INTO t (i) VALUES(1);
RETURN 0;
END;


按照上面定义,下面的语句修改表t,因为myfunc()修改表t, 但是语句不被写进二进制日志,因为它是一个SELECT语句:

 SELECT myfunc();


在一个子程序内执行的语句不被写进二进制日志。假如你发布下列语句:

 CREATE PROCEDURE mysp INSERT INTO t VALUES(1);
CALL mysp;


对于这个例子来说,CREATE PROCEDURE 和CALL语句出现在二进制日志里,但INSERT语句并未出现。在从服务器上,当决定复制哪个来自主服务器的事件时,下列限制被应用:--replicate-*-table规则不适用于CALL语句或子程序内的语句:在这些情况下,总是返回“复制!”
触发程序类似于存储函数,所以前述的评论也适用于触发程序,除了下列情况: CREATE TRIGGER没有可选的DETERMINISTIC特征,所以触发程序被假定为总是确定性的。然而,这个假设在一些情况下是非法的。比如,UUID()函数是非确定性的(不能复制)。你应该小心在 触发程序中使用这个函数。
触发程序目前不能更新表,但是在将来会支持。因为这个原因,如果你没有SUPER权限且log_bin_trust_routine_creators 被设为0,得到的错误信息类似于存储子程序与CREATE TRIGGER产生的错误信息。
到这就介绍完了,最后来总结一下,log_bin_trust_function_creators的作用就是定义create procedure或者create function的时候,屏蔽super权限和去除必须明白地指定 DETERMINISTIC 或 NO SQL与READS SQL DATA 的要求(DETERMINISTIC 或 NO SQL与READS SQL DATA只是声明的作用,而非约束)。
在同步中,如果启用log_bin_trust_function_creators,创建修改表数据的function,可能会导致主从同步不一致。而在用binlog做数据恢复的时候,可能会导致恢复数据不完整而丢失,原因上述已阐明。

--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论