Fujitsu OSS團隊和PostgreSQL開源社區(qū)合作在PG14中添加了在邏輯復(fù)制中對兩階段提交進(jìn)行解密的功能。下面看看這項功能是什么?
背景
兩階段提交是事務(wù)以兩階段進(jìn)行提交的一種機制。通常在分布式數(shù)據(jù)庫中用于保證一致性。事務(wù)的兩階段是PREPARE階段和COMMIT/ROLLBACK階段。PG中兩階段提交的命令是:
PREPARE TRANSACTION
COMMIT PREPARED
ROLLBACK PREPARED
PG在8.0版本已經(jīng)支持了兩階段提交,10.0版本支持邏輯復(fù)制。但是邏輯復(fù)制中一直都不支持兩階段提交。單實例中已經(jīng)支持了PREPARE TRANSACTION、COMMIT PREPARED和ROLLBACK PREPARED命令,但是當(dāng)這些命令需要邏輯復(fù)制到備機時,他們不再保持原始含義。PREPARE TRANSACTION命令被視為NOP,而根本沒有解碼。COMMIT PREPARED命令被視為COMMIT,ROLLBACK PREPARED命令被視為ABORT。
什么是兩階段提交
兩階段提交是一種原子提交協(xié)議,有助于維護分布式數(shù)據(jù)庫之間的一致性。提供數(shù)據(jù)庫內(nèi)原子性的普通提交不足以為跨數(shù)據(jù)庫的事務(wù)提供一致性。為說明這個問題,我們舉一個例子:
1) John在A銀行有300$
2) Mark在B銀行有100$
3) John想給Mark轉(zhuǎn)100$
事務(wù)進(jìn)行過程中,需要從A銀行提取100$到銀行B。事務(wù)結(jié)束的時候,應(yīng)該都有200$.如果在轉(zhuǎn)賬的過程中,任何時候任何一筆交易失敗,那么賬戶狀態(tài)應(yīng)該恢復(fù)到轉(zhuǎn)賬開始前的狀態(tài)。事務(wù)可能因各種原因而失敗。如果在事務(wù)提交之前發(fā)生任何中斷,則該事務(wù)會回滾。在我們的示例中,如果John的賬戶中扣除金額時發(fā)生中斷,那么中斷口John的賬戶不應(yīng)該減少。這就是簡單的提交如何保持?jǐn)?shù)據(jù)庫內(nèi)的一致性。
但是我們考慮這樣一種情況,即從John賬戶中扣除100$的事務(wù)在一次提交時成功,但向Mark在B銀行的賬戶中添加100$的事務(wù)失敗而被回滾。然后此操作結(jié)束后,雖然John賬戶已扣款,但Mark將不會收到該金額。100$消失了。在處理分布式事務(wù)時,簡單的提交有可能失敗。
分布式事務(wù)的分步執(zhí)行
對于兩階段提交,其中一個數(shù)據(jù)庫充當(dāng)分布式事務(wù)的協(xié)調(diào)器。
階段1
一個數(shù)據(jù)庫開始應(yīng)用事務(wù),然后做Prepare。它以prepare消息形式發(fā)送prepared事務(wù)到其它數(shù)據(jù)庫。第2個數(shù)據(jù)庫獲取到Prepare消息,然后prepare該事務(wù)。Prepare涉及事務(wù)中的修改,但不提交。這些臟數(shù)據(jù)寫到磁盤以持久化。一旦所有數(shù)據(jù)庫都prepare了事務(wù),并且有關(guān)該事務(wù)的所有信息都存儲到磁盤上,prepare階段就完成了。
階段2
接下來,仲裁器啟動提交階段。如果第2個數(shù)據(jù)庫由于某種原因未能準(zhǔn)備事務(wù),則仲裁器啟動回滾階段。因此根據(jù)prepare是否成功,事務(wù)要么提交,要么回滾。在最后提交階段發(fā)生中斷是可以恢復(fù)的,因為所需的prepare事務(wù)已經(jīng)寫入磁盤并可以重新應(yīng)用。
兩階段提交與單實例數(shù)據(jù)庫并不相關(guān),但若數(shù)據(jù)復(fù)制跨多個數(shù)據(jù)庫實例時,就相關(guān)了。
邏輯復(fù)制中支持兩階段提交非常重要。
功能概述
在PG14版本前,邏輯復(fù)制事務(wù)僅在事務(wù)提交后才被解碼和復(fù)制。這是為了避免復(fù)制事務(wù)可能最終被中止。
提交時解碼事務(wù)
PG14的邏輯復(fù)制支持PREPARE TRANSACTION、COMMIT PREPARED和ROOLBACK PREPARED命令。當(dāng)PREPARE TRANSACTION命令解碼時,事務(wù)被解碼并復(fù)制。PREPARE TRANSACTION就像WAL SENDER中COMMIT一樣啟動事務(wù)重放和解碼。
prepare時解碼事務(wù)
我們還定義了新的插件回調(diào),允許邏輯解碼插件支持兩階段提交。
回調(diào)函數(shù)
描述
filter_prepare_cb
允許插件根據(jù)PREPARE TRANSACTION命令中使用的GID過濾Prepare時不需要解碼的事務(wù)
begin_prepare_cb
Prepare事務(wù)的開始
prepare_cb
當(dāng)PREPARE TRANSACTION命令被解碼時調(diào)用
commit_prepared_cb
當(dāng)COMMIT PREPARED命令解碼時調(diào)用
rollback_prepared_cb
當(dāng)ROLLBACK PREPARED命令解碼時調(diào)用
插件修改
test_decoding
該插件是一個邏輯解碼輸出插件,作為一個示例幫助用戶開發(fā)自己的邏輯解碼插件。test_decoding通過邏輯解碼機制接收WAL,并將其解碼為所執(zhí)行操作的文本表示。
它被修改為能夠在prepare時使用新的兩階段回調(diào)函數(shù)和解碼事務(wù)
APIs的修改
pg_create_logical_replication_slot()
該API添加了新的選項指定slot是否支持兩階段提交。輸出插件可以使用帶有兩階段選項的復(fù)制槽以支持兩階段提交。
pg_create_logical_replication_slot(slot_name name, plugin name [, temporary boolean, two_phase boolean ] )
案例
看下怎么檢測兩階段提交的事務(wù)解碼輸出:
1) 創(chuàng)建一個復(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)建一個表
postgres=# CREATE TABLE data(id serial primary key, data text);
CREATE TABLE
3) 檢測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對此功能的更改,有了解碼器端的基礎(chǔ)架構(gòu),允許在prepare時解碼兩階段提交。我們還修改了test_decoding插件以利用此基礎(chǔ)架構(gòu)。
下一步就是把對兩階段的支持實現(xiàn)到PG內(nèi)部最大的邏輯解碼插件--pgoutput插件中。這個插件支持邏輯復(fù)制的PUBLISHER/SUBSCRIBER 模式。他是邏輯復(fù)制中使用最廣泛的插件。富士通OSS團隊正在和開源社區(qū)合作,以在PG15中添加此功能。
對于分布式數(shù)據(jù)庫中的兩階段事務(wù),PG也需要支持:備機通知主機PREPARE失敗了,發(fā)起回滾。這種反饋機制在PG中不支持,是未來改進(jìn)的方向之一。
-
解碼器
+關(guān)注
關(guān)注
9文章
1131瀏覽量
40683 -
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3766瀏覽量
64278
發(fā)布評論請先 登錄
相關(guān)推薦
評論