閱讀840 返回首頁    go 阿裏雲 go 技術社區[雲棲]


PostgreSQL 忘記提交2PC事務對數據庫造成的危害.

我在數據庫中開啟了一個2PC事務,但是不去管他,會發生什麼呢?有什麼危害?
postgres=# begin;
BEGIN
postgres=# insert into t6 values (1);
INSERT 25622 1
postgres=# prepare transaction 'a';
PREPARE TRANSACTION
postgres=# select * from txid_current_snapshot();
     txid_current_snapshot     
-------------------------------
 639903995:639904018:639903995
(1 row)
postgres=# select * from pg_prepared_xacts ;
 transaction | gid |           prepared            |  owner   | database 
-------------+-----+-------------------------------+----------+----------
   639903995 | a   | 2015-09-24 10:03:53.900569+08 | postgres | postgres
(1 row)
危害1, 膨脹
因為vacuum 在回收垃圾時,判斷dead tuple可以回收的前提是,dead tuple是在最早未提交事務之前產生的。
所以,在這個事務之後,產生的DEAD TUPLE都無法被回收,即使VACUUM FULL也無法回收。
源碼分析請參考
https://blog.163.com/digoal@126/blog/static/16387704020153305256157/

危害2, 年齡
年齡同樣會受到威脅,最多隻能降低到最早未提交的事務。
例如:
postgres=# select age(datfrozenxid),datfrozenxid,datname from pg_database where datname=current_database();
 age | datfrozenxid | datname  
-----+--------------+----------
  36 |    639903995 | postgres
(1 row)
無法降低年齡了
postgres=# vacuum freeze;
VACUUM
postgres=# select age(datfrozenxid),datfrozenxid,datname from pg_database where datname=current_database();
 age | datfrozenxid | datname  
-----+--------------+----------
  36 |    639903995 | postgres
(1 row)
隨著事務流逝,年齡越來越大
postgres=# insert into t6 values (1);
INSERT 25655 1
postgres=# insert into t6 values (1);
INSERT 25656 1
postgres=# insert into t6 values (1);
INSERT 25657 1
postgres=# insert into t6 values (1);
INSERT 25658 1
postgres=# insert into t6 values (1);
INSERT 25659 1
postgres=# select age(datfrozenxid),datfrozenxid,datname from pg_database where datname=current_database();
 age | datfrozenxid | datname  
-----+--------------+----------
  41 |    639903995 | postgres
(1 row)
postgres=# vacuum freeze;
VACUUM
postgres=# select age(datfrozenxid),datfrozenxid,datname from pg_database where datname=current_database();
 age | datfrozenxid | datname  
-----+--------------+----------
  41 |    639903995 | postgres
(1 row)

危害3, 持鎖,DDL當然也是下不去的。
包括vacuum full, alter table, ....

最後,還需要提醒,基於流複製的備庫,2PC事務會複製過去,激活後就可以看到。
所以2PC是非常堅強的,停庫後起來還在,切換到備庫也還在。
監控必須建立起來,對於長時間不提交的prepared transaction,及時告警。

[參考]
1. https://blog.163.com/digoal@126/blog/static/1638770402012101423358264
2. https://www.postgresql.org/docs/9.4/static/sql-prepare-transaction.html
3. https://www.postgresql.org/docs/9.4/static/sql-commit-prepared.html
4. https://www.postgresql.org/docs/9.4/static/sql-rollback-prepared.html
5. https://www.postgresql.org/docs/9.4/static/view-pg-prepared-xacts.html
6. https://www.postgresql.org/docs/9.4/static/runtime-config-resource.html#GUC-MAX-PREPARED-TRANSACTIONS
7. https://blog.163.com/digoal@126/blog/static/16387704020153305256157/

最後更新:2017-04-01 13:37:07

  上一篇:go PostgreSQL 從文件係統恢複遺失的UNLOGGED table's datafile.
  下一篇:go 手機淘寶性能優化