前言
其实业务应该尽量少的使用replace into;
问题
如果是有id 且有唯一索引的话,按照联合索引做replace into,
主键在数据库里面是先delete 然后再insert
一张mysql表中有id主键和name唯一索引字段,用户使用replace into更新唯一索引字段,当唯一索引重复时,mysql会删除旧数据并插入新数据,但是在binlog中表现是update,导致mergesql取不到需要删除的id,hive多一个旧数据
replace into table(name, col_3) values('bbb', 'b');
id | name | describe | col3 | col4 | |
旧数据 | 1 | aaa | a | a | a |
新数据 | 2 | bbb | b | b |
产生的新数据只有values中的字段,其他字段取默认值
我们的解决方法:
-
binlog增量表记录旧数据,旧数据只包含被更新的字段,如果出现id字段,意味着id被修改过
-
mergesql最后去掉旧数据
replace还需要注意的问题
1、插入可能会导致mysql原有列的数据丢失
2、旧的id有关联别的表,会导致关联丢失
3、replace into会导致自增主键id一直增大,主键id并不连续,但是是连续递增
还有就是:
(replace操作在自增主键的情况下,遇到唯一键冲突时执行的是delete+insert,但是在记录binlog时,却记录成了update操作,update操作不会涉及到auto_increment的修改。备库应用了binlog之后,备库的表的auto_increment属性不变。如果主备库发生主从切换,备库变为原来的主库,写新的主库则有风险发生主键冲突)