PostgreSQL的MVCC

Posted PostgreSQLChina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL的MVCC相关的知识,希望对你有一定的参考价值。

作者:阎书利

基于多个旧值版本的并发控制即MVCC,就是实现一致读。

PostgreSQL为每一个事务分配一个递增的、类型为int32的整数作为唯一的事务ID,即xid。

创建一个新的快照时,将收集当前正在执行的事务id和已提交的最大事务id。

根据快照提供的信息,PostgreSQL可以确定事务的操作是否对执行语句是可见的。

PostgreSQL还在系统里的每一行记录上都存储了事务相关的信息,同样用来判断一行记录对于当前事务是否可见。

在PostgreSQL的内部数据结构中,每个元组(行记录)有4个事务可见性相关的隐藏列:xmin , xmax, cmin, cmax

其中cmin和cmax分别是插入和删除该元组的命令在事务对其他事务的可见性相关;xmin保存了创建该行数据的事务的xid,xmax保存的是删除改行的xid。

sarah=# create table tbl_mvcc(id serial primary key, ival int);
CREATE TABLE

sarah=# insert into tbl_mvcc(ival) values(1);
INSERT 0 1

sarah=# select xmin, xmax, cmin, cmax, id, ival from tbl_mvcc where id=1;
 xmin | xmax | cmin | cmax | id | ival 
------+------+------+------+----+------
  599 |    0 |    0 |    0 |  1 |    1
(1 row)

当插入一行数据时,PostgreSQL会将插入这行数据的事务的xid存储在xmin中。

由回滚的事务或未提交的事务创建的行对于任何其他事务都是不可见的;

sarah=# begin;
BEGIN

sarah=# select txid_current();
 txid_current 
--------------
          622
(1 row)

sarah=# insert into tbl_mvcc(id, ival) values(6,6);
INSERT 0 1

sarah=# select xmin, xmax, cmin, cmax, id, ival from tbl_mvcc where id=6;
 xmin | xmax | cmin | cmax | id | ival 
------+------+------+------+----+------
  622 |    0 |    0 |    0 |  6 |    6
(1 row)

开启另一个会话:

postgres=# select txid_current();
 txid_current 
--------------
          623
(1 row)
sarah=# select * from tbl_mvcc where id=6;
 id | ival 
----+------
(0 rows)

未提交就看不见;

通过xmax值判断事务的更新操作和删除操作:

  1. 如果没有设置xmax值,该事务对于其他事务总是可见的;
  2. 如果他被设置为回滚事务xid,该事务对其他事务也是可见的;
  3. 如果它被设置为一个正在运行,没有commit和rollback的事务xid,该行对其他事务时可见的;
  4. 如果它被设置为一个已提交的事务xid,该行对这个已提交之后发起的所有事务都是不可见的;

以上是关于PostgreSQL的MVCC的主要内容,如果未能解决你的问题,请参考以下文章

MVCC图示

MVCC Postgresql 和 MYSQL 到底谁更......?

关于postgresql中事务隔离的总结

Greenplum的MVCC多版本控制的简单介绍(主要涉及cmin,cmax,xmin,xmax说明)

为啥 MVCC 需要对 DML 语句进行锁定

MySQL中InnoDB的多版本并发控制(MVCC)