这是学习笔记的第 2034 篇文章微信
在前几天碰到了一个奇怪的复制问题,也作了简单的跟踪。并发
MySQL复制问题的分析高并发
没想到今天在作压力测试的时候,又碰到了相似的问题,这个问题的紧要程度要排上了日程。 学习
从binlog日志的解析结果来看,是这样的语句:测试
#190709 17:18:04 server id 182 end_log_pos 398120311 CRC32 0x89d5a523 Update_rows: table id 5252840 flags: STMT_END_Furl
### UPDATE `tbo_db`.`tda_data_20190709`spa
### WHERE.net
### @1=749375136 /* LONGINT meta=0 nullable=0 is_null=0 */日志
### @2=7202 /* INT meta=0 nullable=0 is_null=0 */code
### @3=1 /* INT meta=0 nullable=0 is_null=0 */
### @4='2019-07-09 17:18:04' /* DATETIME(0) meta=0 nullable=0 is_null=0 */
### @5='2019-07-09 17:18:04' /* DATETIME(0) meta=0 nullable=0 is_null=0 */
### @6=0 /* LONGINT meta=0 nullable=0 is_null=0 */
### SET
### @1=749375136 /* LONGINT meta=0 nullable=0 is_null=0 */
--
这个语句乍一看有些不合逻辑,因此按照输出的错误和问题发生的场景。以下的错误彷佛也有必定的道理。
Could not execute Update_rows event on table tbo_db.tda_data_20190709; Can't find record in 'tda_data_20190709',
修复的过程是常规的思路,从主库的binlog中解析获得相关的偏移量位置附近的语句,而后评估是否能够跳过,若是跳过则须要指向下一个GTID事务。
我上次抛出了几个问题,咱们来逐个作下验证:
若是使用相似的语句,在MySQL主库端会直接抛错。
>>update test where id=100 and name='aa' set id=100;
ERROR 1064 (42000):
而若是改成update,set,where的句式,语句能够成功,尽管变动没法匹配到相关数据,可是会生成相关的binlog,从库的复制是正常的.
>>update test set id=100 , name='aa' where id=100;
Query OK, 0 rows affected (0.00 sec)
咱们再来看一个案例,首先咱们看下数据状况:
select * from test;
+----+------+-------+
| id | name | memo1 |
+----+------+-------+
| 1 | aa | NULL |
| 2 | bb | NULL |
+----+------+-------+
2 rows in set (0.00 sec)
建表语句为:
CREATE TABLE `test` (
`id` int(11) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`memo1` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
咱们接着使用正常的update作下变动。
>>update test set id=1 where id=1 and name='aaa';
Query OK, 0 rows affected (0.00 sec)
这种状况下的变动结果显示为0,可是依然是正常执行的。
而查看binlog的状态,会发现生成的update语句也是正常的没有作任何的改变。
#190709 23:37:57 server id 213 end_log_pos 149605040 CRC32 0xc6a341aa Query thread_id=288594 exec_time=0 error_code=0
SET TIMESTAMP=1562686677/*!*/;
update test set id=1 where id=1 and name='aaa'
/*!*/;
# at 149605040
#190709 23:37:57 server id 213 end_log_pos 149605120 CRC32 0x22ffd3a3 Query thread_id=288594 exec_time=0 error_code=0
SET TIMESTAMP=1562686677/*!*/;
到了这里,咱们基本有一个总体的印象了。咱们再来回顾下那个update语句,会发现彷佛where和set子句的顺序写反了。
应该是update set xxxxx where xxxx
而顺着这个思路往下思考,彷佛这个问题也就解释的通了。
对于我来讲,对于这个问题的修复也是须要多方确认,首先须要排除应用端的一些高并发处理的异常状况。
同时在MySQL中查看是否存在一些相关的复制bug,这个问题还会持续跟进。
本文分享自微信公众号 - 杨建荣的学习笔记(jianrong-notes)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。