Fujitsu OSS團(tuán)隊(duì)和PostgreSQL開源社區(qū)合作在PG14中添加了在邏輯復(fù)制中對(duì)兩階段提交進(jìn)行解密的功能。下面看看這項(xiàng)功能是什么?
背景
兩階段提交是事務(wù)以兩階段進(jìn)行提交的一種機(jī)制。通常在分布式數(shù)據(jù)庫(kù)中用于保證一致性。事務(wù)的兩階段是PREPARE階段和COMMIT/ROLLBACK階段。PG中兩階段提交的命令是:
PREPARE TRANSACTION
COMMIT PREPARED
ROLLBACK PREPARED
PG在8.0版本已經(jīng)支持了兩階段提交,10.0版本支持邏輯復(fù)制。但是邏輯復(fù)制中一直都不支持兩階段提交。單實(shí)例中已經(jīng)支持了PREPARE TRANSACTION、COMMIT PREPARED和ROLLBACK PREPARED命令,但是當(dāng)這些命令需要邏輯復(fù)制到備機(jī)時(shí),他們不再保持原始含義。PREPARE TRANSACTION命令被視為NOP,而根本沒有解碼。COMMIT PREPARED命令被視為COMMIT,ROLLBACK PREPARED命令被視為ABORT。
什么是兩階段提交
兩階段提交是一種原子提交協(xié)議,有助于維護(hù)分布式數(shù)據(jù)庫(kù)之間的一致性。提供數(shù)據(jù)庫(kù)內(nèi)原子性的普通提交不足以為跨數(shù)據(jù)庫(kù)的事務(wù)提供一致性。為說明這個(gè)問題,我們舉一個(gè)例子:
1) John在A銀行有300$
2) Mark在B銀行有100$
3) John想給Mark轉(zhuǎn)100$
事務(wù)進(jìn)行過程中,需要從A銀行提取100$到銀行B。事務(wù)結(jié)束的時(shí)候,應(yīng)該都有200$.如果在轉(zhuǎn)賬的過程中,任何時(shí)候任何一筆交易失敗,那么賬戶狀態(tài)應(yīng)該恢復(fù)到轉(zhuǎn)賬開始前的狀態(tài)。事務(wù)可能因各種原因而失敗。如果在事務(wù)提交之前發(fā)生任何中斷,則該事務(wù)會(huì)回滾。在我們的示例中,如果John的賬戶中扣除金額時(shí)發(fā)生中斷,那么中斷口John的賬戶不應(yīng)該減少。這就是簡(jiǎn)單的提交如何保持?jǐn)?shù)據(jù)庫(kù)內(nèi)的一致性。
但是我們考慮這樣一種情況,即從John賬戶中扣除100$的事務(wù)在一次提交時(shí)成功,但向Mark在B銀行的賬戶中添加100$的事務(wù)失敗而被回滾。然后此操作結(jié)束后,雖然John賬戶已扣款,但Mark將不會(huì)收到該金額。100$消失了。在處理分布式事務(wù)時(shí),簡(jiǎn)單的提交有可能失敗。
分布式事務(wù)的分步執(zhí)行
對(duì)于兩階段提交,其中一個(gè)數(shù)據(jù)庫(kù)充當(dāng)分布式事務(wù)的協(xié)調(diào)器。
階段1
一個(gè)數(shù)據(jù)庫(kù)開始應(yīng)用事務(wù),然后做Prepare。它以prepare消息形式發(fā)送prepared事務(wù)到其它數(shù)據(jù)庫(kù)。第2個(gè)數(shù)據(jù)庫(kù)獲取到Prepare消息,然后prepare該事務(wù)。Prepare涉及事務(wù)中的修改,但不提交。這些臟數(shù)據(jù)寫到磁盤以持久化。一旦所有數(shù)據(jù)庫(kù)都prepare了事務(wù),并且有關(guān)該事務(wù)的所有信息都存儲(chǔ)到磁盤上,prepare階段就完成了。
階段2
接下來,仲裁器啟動(dòng)提交階段。如果第2個(gè)數(shù)據(jù)庫(kù)由于某種原因未能準(zhǔn)備事務(wù),則仲裁器啟動(dòng)回滾階段。因此根據(jù)prepare是否成功,事務(wù)要么提交,要么回滾。在最后提交階段發(fā)生中斷是可以恢復(fù)的,因?yàn)樗璧膒repare事務(wù)已經(jīng)寫入磁盤并可以重新應(yīng)用。
兩階段提交與單實(shí)例數(shù)據(jù)庫(kù)并不相關(guān),但若數(shù)據(jù)復(fù)制跨多個(gè)數(shù)據(jù)庫(kù)實(shí)例時(shí),就相關(guān)了。
邏輯復(fù)制中支持兩階段提交非常重要。
功能概述
在PG14版本前,邏輯復(fù)制事務(wù)僅在事務(wù)提交后才被解碼和復(fù)制。這是為了避免復(fù)制事務(wù)可能最終被中止。

提交時(shí)解碼事務(wù)
PG14的邏輯復(fù)制支持PREPARE TRANSACTION、COMMIT PREPARED和ROOLBACK PREPARED命令。當(dāng)PREPARE TRANSACTION命令解碼時(shí),事務(wù)被解碼并復(fù)制。PREPARE TRANSACTION就像WAL SENDER中COMMIT一樣啟動(dòng)事務(wù)重放和解碼。

prepare時(shí)解碼事務(wù)
我們還定義了新的插件回調(diào),允許邏輯解碼插件支持兩階段提交。
回調(diào)函數(shù)
描述
filter_prepare_cb
允許插件根據(jù)PREPARE TRANSACTION命令中使用的GID過濾Prepare時(shí)不需要解碼的事務(wù)
begin_prepare_cb
Prepare事務(wù)的開始
prepare_cb
當(dāng)PREPARE TRANSACTION命令被解碼時(shí)調(diào)用
commit_prepared_cb
當(dāng)COMMIT PREPARED命令解碼時(shí)調(diào)用
rollback_prepared_cb
當(dāng)ROLLBACK PREPARED命令解碼時(shí)調(diào)用
插件修改
test_decoding
該插件是一個(gè)邏輯解碼輸出插件,作為一個(gè)示例幫助用戶開發(fā)自己的邏輯解碼插件。test_decoding通過邏輯解碼機(jī)制接收WAL,并將其解碼為所執(zhí)行操作的文本表示。
它被修改為能夠在prepare時(shí)使用新的兩階段回調(diào)函數(shù)和解碼事務(wù)
APIs的修改
pg_create_logical_replication_slot()
該API添加了新的選項(xiàng)指定slot是否支持兩階段提交。輸出插件可以使用帶有兩階段選項(xiàng)的復(fù)制槽以支持兩階段提交。
pg_create_logical_replication_slot(slot_name name, plugin name [, temporary boolean, two_phase boolean ] )
案例
看下怎么檢測(cè)兩階段提交的事務(wù)解碼輸出:
1) 創(chuàng)建一個(gè)復(fù)制槽
使用test_decoding作為輸出插件,傳入true,這樣slot支持兩階段提交解碼。
postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding', false, true);
slot_name | lsn
-----------------+-----------
regression_slot | 0/16B1970
(1 row)
2) 創(chuàng)建一個(gè)表
postgres=# CREATE TABLE data(id serial primary key, data text);
CREATE TABLE
3) 檢測(cè)prepare事務(wù)和commit事務(wù)的解碼輸出內(nèi)容
postgres=# BEGIN;
postgres=*# INSERT INTO data(data) VALUES('5');
postgres=*# PREPARE TRANSACTION 'test_prepared1';
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+-----------------
0/1689DC0 | 529 | BEGIN 529
0/1689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
0/1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
(3 rows)
postgres=# COMMIT PREPARED 'test_prepared1';
postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+------------------
0/168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529
(4 rows)
postgres=# select * from data;
id | data
----+------
1 | 5
(1 row)
未來
PG14對(duì)此功能的更改,有了解碼器端的基礎(chǔ)架構(gòu),允許在prepare時(shí)解碼兩階段提交。我們還修改了test_decoding插件以利用此基礎(chǔ)架構(gòu)。
下一步就是把對(duì)兩階段的支持實(shí)現(xiàn)到PG內(nèi)部最大的邏輯解碼插件--pgoutput插件中。這個(gè)插件支持邏輯復(fù)制的PUBLISHER/SUBSCRIBER 模式。他是邏輯復(fù)制中使用最廣泛的插件。富士通OSS團(tuán)隊(duì)正在和開源社區(qū)合作,以在PG15中添加此功能。
對(duì)于分布式數(shù)據(jù)庫(kù)中的兩階段事務(wù),PG也需要支持:備機(jī)通知主機(jī)PREPARE失敗了,發(fā)起回滾。這種反饋機(jī)制在PG中不支持,是未來改進(jìn)的方向之一。
-
解碼器
+關(guān)注
關(guān)注
9文章
1225瀏覽量
43789 -
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
4085瀏覽量
68570
發(fā)布評(píng)論請(qǐng)先 登錄
SGM7SZ14:小體積大能量的邏輯反相器
SGM7SZ19:小邏輯 1-of-2 解碼器/多路分配器的技術(shù)剖析
TLV320AIC14:高性能語音編解碼器的深度剖析與應(yīng)用指南
高速CMOS邏輯3 - 8線解碼器/解復(fù)用器:CDx4HC(T)138和'238的技術(shù)解析
CDx4HC(T)138和CDx4HC(T)238:高速CMOS邏輯3 - 8線解碼器的深度解析
發(fā)布元服務(wù)提交審核
流水線基本結(jié)構(gòu)
小紅書獲取筆記正文和點(diǎn)贊數(shù)的API接口
分享一個(gè)嵌入式學(xué)習(xí)階段規(guī)劃
0.1-2.7 GHz SP4T 開關(guān),帶集成邏輯解碼器 skyworksinc
LOTO示波器自定義解碼功能—CANFD解碼
CMOS的邏輯門如何應(yīng)用在電路中
Transformer架構(gòu)中解碼器的工作流程
下一代物聯(lián)網(wǎng):芯科科技和Arduino借助邊緣AI和ML簡(jiǎn)化Matter設(shè)計(jì)和應(yīng)用
PostgreSQL 14中兩階段提交的邏輯解碼正文
評(píng)論