定时任务是我们开发、运维人员经常用到的,比如cron,job,schedule,events scheduler等都是为了方便我们重复执行某项工作而无需人工参与而设计,这里我要说的是MySQL数据库本身的定时任务,即events scheduler的风险案例。
一、现象描述
这里有一个从库出现数据不同步现象,具体报错如下:
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table bs.dg_sale; Can't find record in 'dg_sale', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000079, end_log_pos 159513315
这个现象出现是由于主键问题导致数据删除失败,进而引发数据同步错误。
二、原因分析
出现上述错误比较常见的是从库做了一些删除操作,然后数据同步的时候通过主键寻找条件删除的时候无法执行删除操作,进而导致主从错误。
通过对比主库数据和从库数据发现表数据记录数都是0,然后自增值不同,从库始终没有外部账户访问,这里就有点懵逼了吧?没错,还有一种情况可能导致从库被操作,那就是定时任务。通过排查发现,果然主库设有几个events事件,其中有个定时任务就设计到这个表的多次查询、删除、插入等操作。
正常情况下主库创建event schedule,从库自动的将event disable掉,如果切换需要手动enable event scheduler,如果搭建主从实现创建好的定时任务复制到从库,从库的scheduler可能会被激活,导致主从的scheduler都被执行。
三、处理过程
1.查看从库状态和错误代码信息。
2.检查主库、从库表数据信息、表结构信息。
show slave status \G
show create table bs.dg_sale \G
select count(1) from bs.dg_sale;
3.分析产生错误的binlog信息。
主库:
show binlog events in 'mysql-bin.000079' from 159512534 limit 10;
mysqlbinlog --base64-output='decode-rows' --start-position=159512534 --stop-position=159512838 -vv mysql-bin.000079 >binlog.txt
4.查看主库/从库events scheduler信息
show variables like 'event_scheduler';
show events;
select EVENT_SCHEMA,EVENT_NAME,STATUS ,EXECUTE_AT,INTERVAL_VALUE from events;
这里看到events scheduler
5.禁用从库的events scheduler
set global event_scheduler=0;或者在主创建的时候加入DISABLE ON SLAVE
在从库my.cnf配置文件中加入set global event_scheduler=0
6.重新完成数据同步
四、总结和知识扩展
含有scheduler事件的风险项:
1)主从切换的时候,新主库需要enable scheduler events
2)含有scheduler 的数据库搭建从库,需要特别注意从库的scheduler events需要被disable
1.创建mysql events scheduler
语法:
CREATE [DEFINER = { user | CURRENT_USER }]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE] [COMMENT 'string']
DO event_body;
schedule:
AT timestamp [+ INTERVAL interval] ...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
实例:
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE myschema.mytable SET mycol = mycol + 1;
2.删除mysql events scheduler
语法:
DROP EVENT [IF EXISTS] event_name
3.更改mysql events scheduler
语法:
ALTER [DEFINER = { user | CURRENT_USER }]
EVENT event_name
[ON SCHEDULE schedule] [ON COMPLETION [NOT] PRESERVE]
[RENAME TO new_event_name] [ENABLE | DISABLE | DISABLE ON SLAVE] [COMMENT 'string'] [DO event_body]
实例:
ALTER EVENT no_such_event
ON SCHEDULE
EVERY '2:3' DAY_HOUR;