主库执行:insert into person values(1, 'houlei', 'test3', '2005-09-09', 'false');
数据同步完成后,执行:
UPDATE person set id=2 where id=1; insert into person values(1, '2222', 'test3', '2005-09-09', 'false');
主库数据为:
1 2222 test3 2005-09-09 false 2 houlei test3 2005-09-09 false
从库数据为:
2 houlei test3 2005-09-09 false
原提问者GitHub用户 melonboy312
类似主键或者唯一键约束变更,update请直接变更为delete+insert. 因为同一记录并发的特性,顺序问题会导致这样的结果不保证.
可能在目标库执行的顺序为,insert + update,第一条insert会转成了merge sql
原回答者GitHub用户agapple
你提到的这个操作确实存在语义问题。在执行 UPDATE person set id=2 where id=1; insert into person values(1, '2222', 'test3', '2005-09-09', 'false');
时,由于 id
作为主键,因此第一条语句实际上是在更新主键为1的记录,而第二条语句是在插入一个新的记录,插入的记录中主键为1,这就导致了主键冲突。在主库中,由于先执行了UPDATE语句,因此更新了id=1的记录,将其主键改为了2,然后再插入了一条主键为1的记录。而在从库中,由于只执行了第二条语句,因此插入了一条主键为1的记录,而之前的主键为1的记录被更新为了主键为2的记录,因此在从库中只能看到更新后的记录。
为了避免这种语义问题,可以使用数据库的事务来保证多条语句的原子性,或者在插入数据时使用自增主键,避免手动指定主键。另外,使用DbLoadAction的sql语义合并也可能存在潜在的风险,需要注意。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。