PostgreSQL 數據庫實例只讀鎖定(readonly) - 硬鎖定,軟鎖定,解鎖
作者
digoal
日期
2019-01-30
標籤
PostgreSQL , 只讀 , 鎖定 , readonly , recovery.conf , 恢復模式 , pg_is_in_revoery , default_transaction_read_only
背景
在一些場景中,可能要將數據庫設置為只讀模式。
例如,
1、雲數據庫,當使用的容量超過了購買的限制時。切換到只讀(鎖定)模式,確保用戶不會用超。
2、業務上需要對數據庫進行遷移,準備割接時,可將主庫切換到只讀(鎖定),確保絕對不會有事務寫入。
鎖定的實現方法有若干種。
1、硬鎖定,直接將數據庫切換到恢復模式,絕對不會有寫操作出現。
2、軟鎖定,設置default_transaction_read_only為on,默認開啟的事務為只讀事務。用戶如果使用begion transaction read write可破解。
3、內核層面改進的鎖定,對於雲上產品,鎖定後實際上是期望用戶升級容量,或者用戶可以上去刪數據使得使用空間降下來的。那麼以上兩種鎖定都不適用,需要禁止除truncate, drop操作以外的所有操作的這種鎖定方式。而且最好是不需要重啟數據庫就可以實現。
實現
1 鎖定實例
硬鎖定
1、配置 recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
2、重啟數據庫
pg_ctl restart -m fast
3、硬鎖定,不可破解
postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 row)
postgres=# insert into t1 values (1);
ERROR: cannot execute INSERT in a read-only transaction
postgres=# begin transaction read write;
ERROR: cannot set transaction read-write mode during recovery
軟鎖定
1、設置default_transaction_read_only
postgres=# alter system set default_transaction_read_only=on;
ALTER SYSTEM
2、重載配置
postgres=# select pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)
3、所有會話自動進入read only的默認事務模式。
reload前
postgres=# show default_transaction_read_only ;
default_transaction_read_only
-------------------------------
off
(1 row)
reload後
postgres=# show default_transaction_read_only ;
default_transaction_read_only
-------------------------------
on
(1 row)
postgres=# insert into t1 values (1);
ERROR: cannot execute INSERT in a read-only transaction
4、軟鎖定可破解
postgres=# begin transaction read write;
BEGIN
postgres=# insert into t1 values (1);
INSERT 0 1
postgres=# end;
COMMIT
2 解鎖實例
硬解鎖
1、重命名recovery.conf到recovery.done
cd $PGDATA
mv recovery.conf recovery.done
2、重啟數據庫
pg_ctl restart -m fast
軟解鎖
1、設置default_transaction_read_only
postgres=# alter system set default_transaction_read_only=off;
ALTER SYSTEM
2、重載配置
postgres=# select pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)
3、所有會話自動進入read only的默認事務模式。
reload前
postgres=# show default_transaction_read_only ;
default_transaction_read_only
-------------------------------
on
(1 row)
reload後
postgres=# show default_transaction_read_only ;
default_transaction_read_only
-------------------------------
off
(1 row)
寫恢復
postgres=# insert into t1 values (1);
INSERT 0 1
內核層鎖定
通過修改內核實現鎖定,鎖定後只允許:
1、truncate
2、drop
這樣,用戶可以在鎖定的情況下進行數據清理,可以跑任務的形式,檢查數據是否清理乾淨,進行解鎖設置。
阿里雲RDS PG已支持。
參考
https://www.postgresql.org/docs/11/recovery-config.html
https://www.postgresql.org/docs/11/runtime-config-client.html#RUNTIME-CONFIG-CLIENT-STATEMENT
https://www.postgresql.org/docs/11/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL