MySQL-log_bin_trust_function_creators 报错处理

2018年11月13日18:31:51 发表评论 3,671 views
广告也精彩

今天在创建存储函数时,意外的出现的报错,特此记录过程如下:
MySQL的有个参数log_bin_trust_function_creators,官方文档对这个参数的介绍、解释如下所示:
MySQL-log_bin_trust_function_creators 报错处理

一、log_bin_trust_function_creators功能介绍

二进制日志启用(binlog)后,这个变量就会启用。
它控制是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为0(默认值),用户不得创建或修改存储函数,除非它们具有除CREATE ROUTINE或ALTER ROUTINE特权之外的SUPER权限。 设置为0还强制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性声明函数的限制。 如果变量设置为1,MySQL不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建。

二、排查处理过程

2.1 当开启二进制日志后,如果变量

log_bin_trust_function_creators为OFF  #那么创建或修改存储函数就会报
###报错信息如下:
“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)”这样的错误,如下所示:

2.2 查看Mysql参数

mysql> show variables like 'log_bin';  #查看binlog是否开启
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.00 sec)

mysql>  show variables like '%log_bin_trust_function_creators%'; #查看选项是否开启
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF   |
+---------------------------------+-------+
1 row in set (0.00 sec)
"尝试创建函数,出现报错"
mysql> 
mysql> DELIMITER //
mysql> CREATE FUNCTION GET_UPPER_NAME(emp_id INT)
    -> RETURNS VARCHAR(12)
    -> BEGIN
    ->   RETURN(SELECT UPPER(NAME) FROM TEST WHERE ID=emp_id);
    -> END
    -> //
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)
mysql>

2.3 在调用存储函数时,也会遇到这个错误,如下测试所示:

mysql> DELIMITER ;
mysql> set global log_bin_trust_function_creators=1;   #开启设置
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //
mysql> CREATE FUNCTION GET_UPPER_NAME(emp_id INT)
    -> RETURNS VARCHAR(12)
    -> BEGIN
    ->   RETURN(SELECT UPPER(NAME) FROM TEST WHERE ID=emp_id);
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)  #成功创建

mysql> SELECT ID,
    ->        GET_UPPER_NAME(ID)
    -> FROM TEST;
    -> //
+------+--------------------+
| ID   | GET_UPPER_NAME(ID) |
+------+--------------------+
|  100 | KERRY              |
|  101 | JIMMY              |
+------+--------------------+
2 rows in set (0.00 sec)

mysql> DELIMITER ;
mysql> set global log_bin_trust_function_creators=0;  #关闭参数
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT ID,
    ->        GET_UPPER_NAME(ID)    #查询失败
    -> FROM TEST;
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)
mysql> 

三、报错分析

那么为什么MySQL有这样的限制呢? 因为二进制日志的一个重要功能是用于主从复制,而存储函数有可能导致主从的数据不一致。所以当开启二进制日志后,参数log_bin_trust_function_creators就会生效,限制存储函数的创建、修改、调用。那么此时如何解决这个问题呢?官方文档介绍如下,具体可以参考23.7 Binary Logging of Stored Programs

3.1 解决方法一: 取消限制

1: 如果数据库没有使用主从复制,那么就可以将参数log_bin_trust_function_creators设置为1.

mysql> set global log_bin_trust_function_creators=1;

这个动态设置的方式会在服务重启后失效,所以我们还必须在my.cnf中设置,加上log_bin_trust_function_creators=1,这样就会永久生效。

3.2 解决方法二: 指定函数类型

2:明确指明函数的类型,如果我们开启了二进制日志, 那么我们就必须为我们的function指定一个参数。其中下面几种参数类型里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。这样一来相当于明确的告知MySQL服务器这个函数不会修改数据。

1 DETERMINISTIC 不确定的

2 NO SQL 没有SQl语句,当然也不会修改数据

3 READS SQL DATA 只是读取数据,当然也不会修改数据

4 MODIFIES SQL DATA 要修改数据

5 CONTAINS SQL 包含了SQL语句
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF   |
+---------------------------------+-------+
1 row in set (0.00 sec)

mysql> DROP FUNCTION GET_UPPER_NAME;
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //
mysql> CREATE FUNCTION GET_UPPER_NAME(emp_id INT)
    -> RETURNS VARCHAR(12)
    -> READS SQL DATA #添加此行告诉mysql,我只读取不改变数据。
    -> BEGIN
    ->   RETURN(SELECT UPPER(NAME) FROM TEST WHERE ID=emp_id);
    -> END
    -> //
Query OK, 0 rows affected (0.01 sec)

mysql> DELIMITER ;
mysql> SELECT ID,
    ->        GET_UPPER_NAME(ID)
    -> FROM TEST;
+------+--------------------+
| ID   | GET_UPPER_NAME(ID) |
+------+--------------------+
|  100 | KERRY              |
|  101 | JIMMY              |
+------+--------------------+
2 rows in set (0.00 sec)

至此解决掉MySQL-log_bin_trust_function_creators 报错。
更多精彩:Mysql相关文章

  • QQ精品交流群
  • weinxin
  • 微信公众号
  • weinxin
广告也精彩
admin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: