insert on conflict语法实现了upsert的功能,即在插入发生主键冲突、或唯一约束冲突时,执行on conflict后面的语句,将insert变成update或do nothing避免报错。
语法手册:https://www.postgresql.org/docs/current/sql-insert.html
测试用例:
drop table decoding_test;
CREATE TABLE decoding_test(x integer primary key, y text);
postgres=# select * from decoding_test;
x | y
----+---
12 | 9
postgres=# INSERT INTO decoding_test(x,y) values(12,9) on conflict (x) do nothing;
INSERT 0 1
postgres=# select * from decoding_test;
x | y
----+---
12 | 9
-- 没有报主键冲突,结果上看插入没有效果。
postgres=# INSERT INTO decoding_test(x,y) values(12,9) on conflict (x) do nothing;
INSERT 0 0
postgres=# select * from decoding_test;
x | y
----+---
12 | 9
(1 row)
postgres=# INSERT INTO decoding_test(x,y) values(101,20) on conflict (x) do update set y=EXCLUDED.y;
INSERT 0 1
postgres=#
postgres=# select * from decoding_test;
x | y
-----+----
12 | 9
101 | 20
-- 插入时发生主键冲突,执行后面的update语句,将y更新为400,EXCLUDED表示准备要新插入的这一行数据。
postgres=# INSERT INTO decoding_test(x,y) values(101,400) on conflict (x) do update set y=EXCLUDED.y;
INSERT 0 1
postgres=# select * from decoding_test;
x | y
-----+-----
12 | 9
101 | 400
(2 rows)
注意:后面提到的
speculative insert等价与insert on conflict语法。
执行流程:

INSERT INTO decoding_test(x,y) values(12,9) on conflict (x) do nothing;
INSERT INTO decoding_test(x,y) values(20,9) on conflict (x) do update set y=100;
所以从日志中可能看到3种情况:
情况一: 第一条XLOG_HEAP_INSERT 第二条XLOG_HEAP_CONFIRM
情况二: 第一条XLOG_HEAP_INSERT 第二条XLOG_HEAP_DELETE
情况三: 第一条XLOG_HEAP_HOT_UPDATE
下一篇继续介绍这几种日志被逻辑复制解析后的情况。