背景
1、産品的問題點
- PG 實體Standby節點不支援解析邏輯日志
2、問題點背後涉及的技術原理
- 解析邏輯日志需要記錄解析的WAL日志LSN位點(通過slot功能實作), 以便執行個體重新開機或解析任務重新開機後實作斷點續傳, 但是實體Standby節點是RO模式, 不支援寫入(slot lsn位點記錄), 是以Standby節點不支援解析邏輯日志.
- 另一方面, 為了解析邏輯日志, 需要保留catalog的舊版本, 用于讀取對應WAL record對應資料庫對象(例如table)當時對應的資料結構, 進而解析出WAL record的邏輯資料. 而這個動作需要與VACUUM垃圾回收關聯, 防止vacuum把catalog的舊版本清理掉(例如資料庫發生DDL(如修改了表結構), 會導緻catalog的版本發生變化, 老的catalog記錄就變成舊版本, 舊版本可能被vacuum垃圾回收)
3、這個問題将影響哪些行業以及業務場景
- 有較多邏輯增量同步的場景
- 有跨城市進行邏輯增量同步的場景
4、會導緻什麼問題?
- 每個邏輯增量解析鍊路都有1個程序負責, 當有較多邏輯增量同步鍊路時, 如果主節點的寫操作較為頻繁, 産生的WAL日志較多, 那麼解析邏輯日志的CPU、IO壓力也會較大, 影響主執行個體.
- 當有跨城市邏輯增量複制的需求時, 由于邏輯增量日志需要在事務結束時才能解析(為了保證原子性), 然後發送給下遊, 容易産生較大延遲, 一般高于實體流複制的延遲.
原子性:
postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');
lsn | xid | data
-----------+-----+--------------------------------------------------
0/16D30F8 | 691 | BEGIN
0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'
0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'
0/16D32A0 | 691 | COMMIT
0/16D32D8 | 692 | BEGIN
0/16D3398 | 692 | table public.data: DELETE: id[int4]:2
0/16D3398 | 692 | table public.data: DELETE: id[int4]:3
0/16D3398 | 692 | COMMIT
(8 rows)
5、業務上應該如何避免這個坑
- 暫時無解
6、業務上避免這個坑犧牲了什麼, 會引入什麼新的問題
7、資料庫未來産品疊代如何修複這個坑
- 核心層支援standby slot, 通過feedback回報給主庫保留對應的catalog版本.