崩潰恢復場景: 用例
下面我們在 PostgreSQL 的數據庫中,創建一個表,插入一些數據。
CREATE TABLE t (id integer, name text);
INSERT INTO t (id, name)
SELECT i, repeat('Pg', 32)
FROM generate_series(1, 1000000) AS s(i);
下面我們啟動一個事務塊,創建一個空表t1
,復制表t
創建一個新表t_copy
,并查看下表文件的存儲路徑。
BEGIN;
CREATE TABLE t1 ();
CREATE TABLE t_copy AS TABLE t;
SELECT pg_relation_filepath(name) AS path
FROM (VALUES ('t1'), ('t_copy')) AS t (name);
path
--------------
base/5/16389
base/5/16392
讓我們立即停止數據庫,模擬數據庫異常宕機的故障,再重新啟動數據庫服務:
$ pg_ctl stop --mode=immediate
$ pg_ctl start
數據庫重新啟動后,手動觸發一次檢查點:
CHECKPOINT;
檢查重啟前事務塊中新增的表文件:
$ ls -lh base/5/{16389,16392}
-rw------- 1 postgres postgres 0 Aug 18 17:43 base/5/16389
-rw------- 1 postgres postgres 97M Aug 18 17:44 base/5/16392
崩潰恢復場景: 內部原理
下面是我們在 PostgreSQL 的事務中創建表文件時,崩潰恢復后出現表文件殘留問題的內部原因:
- 1. PostgreSQL 在事務運行的過程中,會在會話內存中記錄創建的表文件。
- 2. 當事務發生異?;蛘邎绦谢貪L操作時,會即時地清除這些表文件。
- 3. 當事務異常中斷,如:磁盤不足引發的 PANIC 錯誤,系統發出的 OOM 內存不足信號,或者發生軟件錯誤的擴展插件,系統停電導致的服務器崩潰時,會話內存中記錄的新增表文件會丟失,出現表文件殘留的問題。
Redrock Postgres 的解決方案
Redrock Postgres 在創建表文件時,會記錄撤消日志,當正在連接的會話因為某些原因被中止后,數據庫重新啟動后會檢查這些異常中止的事務。數據庫會回滾這些異常中止的事務,根據記錄的撤消日志清理殘留的表文件。
下面我們在 Redrock Postgres 的數據庫中,創建和上面相同的表,并插入同樣的數據。
CREATE TABLE t (id integer, name text);
INSERT INTO t (id, name)
SELECT i, repeat('Pg', 32)
FROM generate_series(1, 1000000) AS s(i);
下面我們啟動一個事務塊,創建一個空表t1
,復制表t
創建一個新表t_copy
,并查看下表文件的存儲路徑。
BEGIN;
CREATE TABLE t1 ();
CREATE TABLE t_copy AS TABLE t;
SELECT pg_relation_filepath(name) AS path
FROM (VALUES ('t1'), ('t_copy')) AS t (name);
path
--------------
base/5/16389
base/5/16392
讓我們立即停止數據庫,模擬數據庫異常宕機的故障,再重新啟動數據庫服務:
$ pg_ctl stop --mode=immediate
$ pg_ctl start
數據庫重新啟動后,手動觸發一次檢查點:
CHECKPOINT;
事務回滾的時候不會立即清理殘留的表文件,表文件的實際清理操作是在檢查點的過程中完成的。
檢查重啟前事務塊中新增的表文件:
$ ls -lh base/5/{16389,16392}
ls: cannot access 'base/5/16389': No such file or directory
ls: cannot access 'base/5/16392': No such file or directory
數據庫重新啟動后,回滾了異常中止的事務,根據事務記錄的撤消日志清理了殘留的表文件。
轉自:https://mp.weixin.qq.com/s/98DnaCDJPcjFTS2JpxlRYg?
該文章在 2025/8/19 10:21:13 編輯過