簡體   English   中英

Postgresql 在邏輯復制中跳過事務

[英]Postgresql skip transaction in logical replication

在我們公司,我們使用了邏輯復制(在服務器源和接收器上,我們都有 Postgresql 10.5 版本),有時邏輯復制因錯誤而關閉:錯誤:重復鍵值違反唯一約束。

在 pg_replication_origin_status 中,我看到位置 remote_lsn(它是接收器到達的源上的位置)。 我知道如何使用 pg_replication_origin_advance,而且我知道這個函數可能會跳過一些數據。 有沒有辦法在remote_lsn之后獲取下一個位置,這樣數據就不會丟失?

您是否確實確定了哪個表導致了這種情況。 這通常是由在其表定義中使用序列的表引起的。 序列不會在 PostgreSQL 中復制。 目標可以嘗試從頭開始序列並為序列生成值 1。 這是因為邏輯復制不會復制序列的值,因為序列的下一個值沒有存儲在表本身中。

解決方法:

  • 使用外部來源作為數字,如 zookeeper
  • 為不同的服務器使用不重疊的范圍

這是因為 PostgreSQL 中的序列的工作方式:

在源頭考慮這個表,有一個序列:

src=# CREATE TABLE s (a serial PRIMARY KEY, b text);
CREATE TABLE
src=# INSERT INTO s (b) VALUES ('foo'), ('bar'), ('baz');
INSERT 0 3
src=# SELECT * FROM s;
 a |  b
---+-----
 1 | foo
 2 | bar
 3 | baz
(3 rows)

src=# SELECT currval('s_a_seq'), nextval('s_a_seq');
 currval | nextval
---------+---------
       3 |       4
(1 row)

創建序列 s_a_seq 以支持串行類型的 a 列。 這將生成 sa 的自動遞增值 現在讓我們將其復制到 dst 中,並插入另一行:

dst=# SELECT * FROM s;
 a |  b
---+-----
 1 | foo
 2 | bar
 3 | baz
(3 rows)

dst=# INSERT INTO s (b) VALUES ('foobaz');
ERROR:  duplicate key value violates unique constraint "s_pkey"
DETAIL:  Key (a)=(1) already exists.
dst=#  SELECT currval('s_a_seq'), nextval('s_a_seq');
 currval | nextval
---------+---------
       1 |       2
(1 row)

哎呀,剛剛發生了什么? 目標嘗試從頭開始序列並為 a 生成值 1。 這是因為邏輯復制不會復制序列的值,因為序列的下一個值沒有存儲在表本身中。

解決方法

如果從邏輯上考慮,如果沒有雙向同步,就不能從兩個地方修改相同的“自動增量”值。 如果您確實需要在表的每一行中增加一個數字,並且需要從多個服務器插入到該表中,您可以:

  • 使用外部來源的數字,如 ZooKeeper 或 etcd,
  • 使用不重疊的范圍——例如,第一個服務器生成並插入 1 到 100 萬范圍內的數字,第二個服務器生成和插入 100 萬到 200 萬范圍內的數字,依此類推。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM