故障分析--主从复制故障1

时间:2022-08-18 23:42:51

报错内容

2016-04-29 00:09:57 9242 [ERROR] Slave SQL: Error '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)' on query. Default database: 'epsp_db'. Query: 'CREATE DEFINER=`unionpayb2b`@`%` FUNCTION `currval`(v_seq_name VARCHAR(50)) RETURNS int(11) BEGIN 
    DECLARE val,val1 INTEGER;  
    SET val = 0;  
    SELECT current_val INTO val1  FROM tbl_sequence WHERE seq_name = v_seq_name; 
    IF (val1 IS NULL)THEN
    INSERT INTO tbl_sequence VALUES(v_seq_name,0,1);
    ELSE
    SET val=val1;
    END IF;
    RETURN val;  
END', Error_code: 1418
2016-04-29 00:09:57 9242 [Warning] Slave: 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) Error_code: 1418
2016-04-29 00:09:57 9242 [Warning] Slave: Failed to CREATE FUNCTION currval Error_code: 1307
2016-04-29 00:09:57 9242 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.000002' position 326441
2016-04-29 00:10:01 9242 [Note] /data/mysql/base/bin/mysqld: Normal shutdown

 

错误分析1

根据错误信息得知由于创建的这个函数对数据的操作对于replication场景,存在不确定性,也就是说这个函数在主库和从库上执行可能产生不一样的结果。
所以该函数在从库应用时产生了错误,并导致从库sql apply中断,错误信息中也记录了中断的文件及对应的position点

 

错误分析2

根据错误信息给出的提示,可能需要设置log_bin_trust_function_creators这个变量来解决这个错误
通过查询官方文档,得知了该参数的含义:

    log_bin_trust_function_creators
    
        这是一个安全参数,针对于主从复制时对于函数和触发器的处理,默认值为0,表示不允许对数据操作存在不确定性的函数和触发器的创建,因为这类语句会导致主从数据不一致的情况发生。
    
    同时官方文档对这类语句产生不一致的场景进行了进一步说明:
    
        通常二进制日志设置为statement或mixed格式时会出现这种情况,如果是row格式则不会,因为row格式不是记录的对这个函数的调用语句,而是记录的函数调用后对行的改变的记录。
        同样对于触发器也是一样。所以在基于row格式的情况下不会发生这种不一致的情况。
        mixed格式虽然会根据不同的情况动态的使用statement或row格式,但对于函数和触发器,mixed总是使用statement方式进行记录,所以基于mixed格式也会存在这种问题。
    
    官方链接说明:
        https://dev.mysql.com/doc/refman/5.7/en/stored-programs-logging.html

 

解决办法

[master/slave]修改二进制日志格式为row格式
  SHOW VARIABLES LIKE 'BIN%';
  SET GLOBAL BINLOG_FORMAT=ROW
  SET SESSION BINLOG_FORMAT=ROW
  #vi /etc/my.cnf
   ##add
    binlog_format = 1 [master/slave]修改log_bin_trust_function_creators参数,将其设置为1
  SHOW VARIABLES LIKE 'LOG_BIN_TRUST_FUNCTION_CREATORS';
SET GLOBAL log_bin_trust_function_creators = 1;

提前启用该参数,避免主从复制时函数或触发器导致从库复制中断的问题,
但由于该参数开启后,如果不是基于row格式的复制,很难保证当执行相关自定义的函数时,对数据的操作在主从上是一致的,存在不确定性,这也是为什么MySQL默认是
禁止这类函数和触发器的原因,目的是为了保持主从数据的一致性。所以建议可能的情况下,还是采用基于row格式的复制,并开启该参数,避免产生相关错误。
同时也要关注不同的日志格式的区别及对性能的影响。