MySQL主库大表执行delete语句,Ctrl+C具体发生了什么分析
1、查看表结构
localhost.qt>show create table doctor_stats_backup\G
*************************** 1. row ***************************
Table: doctor_stats_backup
Create Table: CREATE TABLE `doctor_stats_backup` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`uid` int(10) unsigned NOT NULL DEFAULT '0',
`typeact` tinyint(3) unsigned NOT NULL DEFAULT '0',
`flag` tinyint(3) unsigned NOT NULL DEFAULT '1',
`intime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`qid` int(10) unsigned NOT NULL DEFAULT '0',
`rid` int(10) unsigned NOT NULL DEFAULT '0',
KEY `intime` (`intime`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
2、查看行数
localhost.qt>select count(*) from doctor_stats_backup;
+-----------+
| count(*) |
+-----------+
| 174541079 |
+-----------+
1 row in set (0.00 sec)
3、在主库上执行delete然后CTRL+C
4、从库收到告警,主从已经中断
5、再分别查看主从doctor_stats_backup的行数
主库
从库
可以见主库上已经删除5499096行,而从库并没有进行删除操作;推断是主库的binglog没有传递到从库,造成了主从不一致,接下来分析下binlog查看原因。
6.查看binlog
主库
可以看到,mysql对delete操作开启了一个事务
从库
Binlog里并没有看到delte操作;从库开启了log-slave-update,只有binglog回放后才会记录到binlog,现在查看从库的relay-log
在从库的relay-log里可以看到delete操作,但是为什么会不执行呢?
参照http://itlab.idcquan.com/linux/MYSQL/918702_3.html对CTRL+C源码的分析,MySQL客户端捕获信号后,向服务器端发送KILL /*!50000 QUERY */ 命令并执行,从而将Query处理kill。
DuringUPDATEorDELETEoperations, the kill flag is checked after each block read and after each updated or deleted row. If the kill flag is set, the statement is aborted. If you are not using transactions, the changes are not rolled back.
对于update、delete数据更新操作,CTRL+C会将执行的操作标记为KILLED状态,然后执行回滚操作。但是如果没有开启事务或者引擎不支持事务,则不会执行回滚。
这样就可以理解了,主库delete过程中执行CTRL+C操作,kill掉了query id而需要进行回滚;由于doctor_stats_backup表是MyISAM表,不能进行回滚--则mysql把binlog打上标记,从库接收主库传过来有标记的binlog也就不执行了,所以从库的relaylog里有delete语句而binlog里没有。
至于是什么标记呢?我们需要动手做实验找找了:
再次delete一次数据,不执行CTRL+C,观察binglog:
对比发现执行了CTRL+C的delete操作的binlog里包含error_code=1317,而不执行CTRL+C的delete操作的binlog里包含error_code=0;答案出现了正是error_code=1317告诉从库不执行这条binlog,而弹出了
错误。
下面我们把doctor_stats_backup表的引擎修改为innodb,再重复上面的实验:
Innodb可以正常的回滚,binlog里不留下一点痕迹,也就不存在主从不同步了。