mysql的replace语句先删除在插入,binlog是如何监听的?

一、replace into语法

官网信息.png

官网地址:https://dev.mysql.com/doc/refman/5.6/en/replace.html

可以看到,replace into的语法描述就是:如果新插入行的主键或唯一键在表中已经存在,则会删除原有记录并插入新行;如果在表中不存在,则直接插入。

二、binlog同步的replace into语句

搭建环境:
mac下mysql如何开启binlog
JAVA实现mysql的binlog监听(mysql-binlog-connector)

2.1 表中不存在

测试sql:

replace into t_user(id,age,name) Values(1,3,'tt');

binlog监听到的数据:

监听的事件类型:QUERY
监听的事件类型:TABLE_MAP
监听的事件类型:EXT_WRITE_ROWS
11:46:17.379 [main] INFO com.tellme.test.TestReplace - {"includedColumns":{"empty":false},"rows":[[1,"tt",3]],"tableId":70}
监听的事件类型:XID

结论:可以看到就是一条insert语句操作;

2.2 表中存在

测试sql

replace into t_user(id,age,name) Values(1,4,'tt');

binlog监听到的数据:

监听的事件类型:QUERY
监听的事件类型:TABLE_MAP
监听的事件类型:EXT_UPDATE_ROWS
11:48:44.897 [main] INFO com.tellme.test.TestReplace - {"includedColumns":{"empty":false},"includedColumnsBeforeUpdate":{"empty":false},"rows":[{"key":[1,"tt",3],"value":[1,"tt",4]}],"tableId":70}
监听的事件类型:XID

结论:可以看到就是一条update语句操作;

2.3 结论

当表中存在唯一键时,replace语句在主库就是删除+插入操作,但是在从库就只是update操作(binlog下发)。

三、replace into的风险

由2.3的结论可知道,主库和从库执行的sql并不是相同的,可能会带来一些风险(主从一致性即主库的AUTO_INCREMENT可能会比从库的AUTO_INCREMENT要高,当主从切换时,可能会出现重复key的异常)

3.1 场景1:只命中唯一索引

CREATE TABLE `t_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '名字',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

使用场景:更新场景下,我们查询到旧数据,然后将需要更换的值填充到旧对象中,然后将其旧对象使用replace into的语法更新到数据库中。假设此时只是命中了主键id(唯一索引)。
场景:

replace into t_user(id,age,name) Values(1,4,'tt');

此时:主库和从库的AUTO_INCREMENT会保持一致,不会出现上述现象。

3.2 场景2:只命中普通字段的唯一索引

表结构:

CREATE TABLE `t_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '名字',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`),
  UNIQUE KEY `union_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

执行sql(关键点,没有将id传入)

replace into t_user(age,name) Values(5,'tt4');

binlog监听:

监听的事件类型:QUERY
监听的事件类型:TABLE_MAP
监听的事件类型:EXT_UPDATE_ROWS
13:05:46.616 [main] INFO com.tellme.test.TestReplace - {"includedColumns":{"empty":false},"includedColumnsBeforeUpdate":{"empty":false},"rows":[{"key":[6,"tt4",4],"value":[7,"tt4",5]}],"tableId":74}

结论:此时主库插入了一条id=7的记录,故主库的AUTO_INCREMENT会变为8,同步给从库的语句只是一条update语句,从库的AUTO_INCREMENT依旧为7。在主从切换时,便会出现上述的问题。

3.3 命中主键和普通字段唯一索引

表结构见3.2:

表数据:


表中数据.png

诉求:表中查询到旧记录(3,'tt3',1),前端传入的是将tt3修改了tt2。经过转化语句变成了:

replace into t_user(id,name,age) Values(3,tt2',1);

由此可见:影响的是3条记录(而非之前认知2条数据)


image.png

sql执行后的结果:

image.png

原理:因为命中了唯一索引id和唯一索引name两个字段。

主库:会先执行delete name='tt2'和delete id='3'的操作,然后在执行insert name='tt2' and id='3'故产生了3条语句。

从库:先删除了id=3的记录,然后将(2,'tt2',13)更换成了(3,"tt2",1)。

监听的事件类型:QUERY
监听的事件类型:TABLE_MAP
监听的事件类型:EXT_DELETE_ROWS
13:21:08.322 [main] INFO com.tellme.test.TestReplace - {"includedColumns":{"empty":false},"rows":[[3,"tt3",1]],"tableId":74}
监听的事件类型:EXT_UPDATE_ROWS
13:21:08.322 [main] INFO com.tellme.test.TestReplace - {"includedColumns":{"empty":false},"includedColumnsBeforeUpdate":{"empty":false},"rows":[{"key":[2,"tt2",13],"value":[3,"tt2",1]}],"tableId":74}
监听的事件类型:XID

结论:可能会产生一些非预期内的问题。即在实现的时候没有料想到会命中其他字段的唯一索引。

四、结论

replace语句虽然可以比较快捷的实现我们的需求,但是并不太推荐使用。

风险点:

  1. 可能造成主从不一致的情况;
  2. 存在多个唯一索引时,可能会产生预期外的sql执行;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容