[英]PostgresQL: Is an entire transaction always written to a replication slot?
我創建了一個復制槽:
SELECT * FROM pg_create_logical_replication_slot('boxoffice_slot', 'test_decoding');
事務中的每個步驟在復制槽中都有自己的行。 下面是一個例子:
lsn | xid | data
-------------+---------+---------------
34A/7000028 | 1311904 | BEGIN 1311904
34A/70020E0 | 1311904 | table cad.purchases: INSERT: id[integer]:754862
34A/70020E1 | 1311904 | table cad.purchases: INSERT: id[integer]:754863
34A/7000028 | 1311904 | COMMIT 1311904
問題:
在事務生命周期的哪個點,事務步驟開始寫入復制槽?
是否有可能在提交事務之前將事務步驟寫入復制槽?
換句話說,是否有可能在任何給定時間只將一半事務寫入復制槽,如下所示:
lsn | xid | data
-------------+---------+---------------
34A/7000028 | 1311904 | BEGIN 1311904
34A/70020E0 | 1311904 | table cad.purchases: INSERT: id[integer]:754862
非常感謝您對此的見解。
事務根本不會寫入復制槽。 它們被寫入 WAL。 肯定會發生只有部分事務寫入 WAL 的情況,例如,如果處理被中斷。
部分寫入的事務將在會話結束時(或在服務器崩潰的恢復期間)自動標記為回滾。
復制槽所容納的數據並不多於 LSN(日志序列號)。 它們是在 WAL 中標記位置的持久數據結構。 這樣主服務器就不會丟棄消費者仍然需要的任何 WAL。 當消費者處理 WAL 時,它會推進復制槽的 LSN,以便主服務器可以丟棄已經消耗的 WAL。
事務中的所有內容都在發生時寫入復制槽。 如果事務回滾,則將回滾輸入 WAL。 如果流在事務中間中斷,則事務不會在訂閱者端提交,至少在重新建立連接之前不會提交。
一種測試方法是創建一個復制槽,然后在另一個終端中,使用pg_recvlogical
查看更改:
pg_recvlogical -d postgres --slot <slot_name> --start --verbose -f -
如果您BEGIN
事務,創建一個表並插入一百萬行到它,你會看到write up to
和flush to
值都在增加,即使交易沒有得到提交/回滾。 這告訴我們更改正在傳播到接收器端:
# pg_recvlogical -d postgres --slot regression_slot --start --verbose -f -
pg_recvlogical: starting log streaming at 0/0 (slot regression_slot)
pg_recvlogical: streaming initiated
pg_recvlogical: confirming write up to 0/0, flush to 0/0 (slot regression_slot)
pg_recvlogical: confirming write up to 0/DF5E620, flush to 0/DF5E620 (slot regression_slot)
pg_recvlogical: confirming write up to 0/DF5E620, flush to 0/DF5E620 (slot regression_slot)
pg_recvlogical: confirming write up to 0/12E01AB8, flush to 0/12E01AB8 (slot regression_slot)
pg_recvlogical: confirming write up to 0/12E01AF0, flush to 0/12E01AF0 (slot regression_slot)
此外,如果您在交易結束前后在終端中查看pg_current_wal_lsn()
,您將看到 LSN 增加,即使您回滾:
pg_current_wal_lsn
--------------------
0/DF5E620
(1 row)
postgres=# begin;
BEGIN
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/DF5E620
(1 row)
postgres=# insert into abc values (generate_series(1,1000000),'foobar');
INSERT 0 1000000
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/1243C000
(1 row)
postgres=# rollback;
ROLLBACK
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/12E01AB8
(1 row)
基於以下測試,我得出結論,只有在提交事務后才將事務插入到復制槽中。
testing=# BEGIN;
BEGIN
testing=# SELECT * FROM pg_logical_slot_get_changes('testing_slot', NULL, NULL);
lsn | xid | data
-----+-----+------
(0 rows)
testing=# insert into person values (generate_series(1,10));
INSERT 0 10
testing=# SELECT * FROM pg_logical_slot_get_changes('testing_slot', NULL, NULL);
lsn | xid | data
-----+-----+------
(0 rows)
testing=# COMMIT;
COMMIT
testing=# SELECT * FROM pg_logical_slot_get_changes('testing_slot', NULL, NULL);
lsn | xid | data
------------+----------+-----------------------------------------------------------
D/23426BC0 | 16171153 | BEGIN 16171153
D/23426BC0 | 16171153 | table public.person: INSERT: name[character varying]:'1'
D/23427078 | 16171153 | table public.person: INSERT: name[character varying]:'2'
D/234270B8 | 16171153 | table public.person: INSERT: name[character varying]:'3'
D/234270F8 | 16171153 | table public.person: INSERT: name[character varying]:'4'
D/23427138 | 16171153 | table public.person: INSERT: name[character varying]:'5'
D/23427178 | 16171153 | table public.person: INSERT: name[character varying]:'6'
D/234271B8 | 16171153 | table public.person: INSERT: name[character varying]:'7'
D/234271F8 | 16171153 | table public.person: INSERT: name[character varying]:'8'
D/23427238 | 16171153 | table public.person: INSERT: name[character varying]:'9'
D/23427278 | 16171153 | table public.person: INSERT: name[character varying]:'10'
D/23427320 | 16171153 | COMMIT 16171153
(12 rows)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.