上周在MHA架构中,测试通过存储过程构建大量的数据,在主服务器执行存储过程后,从服务器的日志和slave状态中看到异常错误,日志文件抛出Error_code: 1418代码,记录下解决办法。
错误日志:
2021-08-16T01:25:52.924913Z 32 [Note] Slave SQL thread for channel '' initialized, starting replication in log 'mysql-bin.000011' at position 12828, relay log './rac2-relay-bin.000022' position: 13001
2021-08-16T01:25:52.925756Z 33 [ERROR] Slave SQL for channel '': Worker 1 failed executing transaction '5ed107db-f4f8-11eb-8c05-0050568f8774:152' at master log mysql-bin.000011, end_log_pos 13393; 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: 'db'. Query: 'CREATE DEFINER=`root`@`localhost` FUNCTION `randstring`(n int) RETURNS varchar(255) CHARSET latin1
begin
declare all_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
declare return_str varchar(255) default '' ;
declare i int default 0 ;
while i<n
do
set return_str = concat( return_str, substring(all_str, floor(1+rand()*52) ,1) ) ;
set i=i+1 ;
end while ;
return return_str ;end', Error_code: 1418
2021-08-16T01:25:52.925828Z 32 [Warning] Slave SQL for channel '': ... The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details). Error_code: 1756
2021-08-16T01:25:52.925923Z 32 [Note] Slave SQL thread for channel '' exiting, replication stopped in log 'mysql-bin.000011' at position 12828
造成的原因:
在mysql中,CREATE PROCEDURE, CREATE FUNCTION, ALTER PROCEDURE,ALTER FUNCTION,CALL, DROP PROCEDURE, DROP FUNCTION等语句都会被写进二进制日志,然后在从服务器上执行。但是,一个执行更新的不确定子程序(存储过程、函数、触发器)是不可重复的,在从服务器上执行(相对与主服务器是重复执行)可能会造成恢复的数据与原始数据不同,从服务器不同于主服务器的情况。
解决办法:设置log_bin_trust_function_creators=1或者将该参数加入到/etc/my.cnf配置文件中
mysql> stop slave;
Query OK, 0 rows affected (0.04 sec)mysql> set global log_bin_trust_function_creators=on;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.12 sec)
关于log_bin_trust_function_creators,它控制是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为0(默认值),用户不得创建或修改存储函数,除非它们具有除CREATE ROUTINE或ALTER ROUTINE特权之外的SUPER权限。 设置为0还强制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性声明函数的限制。 如果变量设置为1,MySQL不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建。