请勿滥用 2PC prepared transaction

简介: 我在数据库中开启了一个2PC事务,但是不去管他,会发生什么呢?有什么危害?postgres=# begin;BEGINpostgres=# insert into t6 val...
我在数据库中开启了一个 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也无法回收。
源码分析请参考

危害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,及时告警。
目录
相关文章
|
7月前
|
Java 数据库连接 mybatis
项目移植到原先mybasis项目里出现BindingException: Invalid bound statement (not found): **selectPage
项目移植到原先mybasis项目里出现BindingException: Invalid bound statement (not found): **selectPage
74 1
|
7月前
|
开发工具 git
解决pre-commit hook failed (add --no-verify to bypass)的问题
该文介绍了两种免去Git预提交钩子(pre-commit)的方法。一是直接进入项目.git/hooks目录,使用`rm -rf ./git/hooks/pre-commit`命令删除pre-commit文件。二是提交时添加`--no-verify`参数,如`git commit --no-verify -m"XXX"`,以跳过预提交检查。
294 0
marven编译时:<pre>错误: 不允许使用自关闭元素</pre>
marven编译时:<pre>错误: 不允许使用自关闭元素</pre>
99 0
|
自然语言处理 Python
A reportable application error has occurred. Conda has prepared the above report......
A reportable application error has occurred. Conda has prepared the above report......
241 0
A reportable application error has occurred. Conda has prepared the above report......
|
SQL Java 关系型数据库
开发指南—Prepared语句
本文介绍了Prepare协议的概念、用途及在Java中的开启方法。
SAP QM 执行事务代码QA11 报错- Selected set code does not exist, or data entered is incomplete-
SAP QM 执行事务代码QA11 报错- Selected set code does not exist, or data entered is incomplete-
SAP QM 执行事务代码QA11 报错- Selected set code does not exist, or data entered is incomplete-
SAP MM 执行事务代码MRRL报错-No message was found for partner 100065 company code 0001-
SAP MM 执行事务代码MRRL报错-No message was found for partner 100065 company code 0001-
SAP MM 执行事务代码MRRL报错-No message was found for partner 100065 company code 0001-
|
存储 关系型数据库
RocksDB Write Prepared Policy
--- title: MySQL · RocksDB · Write Prepared Policy author: 张远 --- # 背景 早期RocksDB TransactionDB将事务的更新操作都缓存在WriteBatch中,事务提交时才写WAL和memtable。RocksDB支持二阶段提交(2PC)后,在prepare阶段写WAL, WriteBatch写memt
2637 0
下一篇
DataWorks