原创文章,同步发自作者个人博客。转载请务必将下面这段话置于文章开头处。
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/sql/mvcc/
PostgreSQL针对ACID的实现机制
事务的实现原理可以解读为RDBMS采取何种技术确保事务的ACID特性。PostgreSQL针对ACID的实现技术如下表所示。
ACID | 实现技术 |
---|---|
原子性(Atomicity) | MVCC |
一致性(Consistency) | 约束(主键、外键等) |
隔离性 | MVCC |
持久性 | WAL |
从上表可以看到,PostgreSQL主要使用MVCC和WAL两项技术实现ACID特性。实际上,MVCC和WAL这两项技术都比较成熟,主流关系型数据库中都有相应的实现,但每个数据库中具体的实现方式往往存在较大的差异。本文将介绍PostgreSQL中的MVCC实现原理。
PostgreSQL中的MVCC原理
事务ID
在PostgreSQL中,每个事务都有一个唯一的事务ID,被称为XID。注意:除了被BEGIN - COMMIT/ROLLBACK包裹的一组语句会被当作一个事务对待外,不显示指定BEGIN - COMMIT/ROLLBACK的单条语句也是一个事务。
数据库中的事务ID递增。可通过txid_current()
函数获取当前事务的ID。
隐藏多版本标记字段
PostgreSQL中,对于每一行数据(称为一个tuple),包含有4个隐藏字段。这四个字段是隐藏的,但可直接访问。
- xmin 在创建(insert)记录(tuple)时,记录此值为插入tuple的事务ID
- xmax 默认值为0.在删除tuple时,记录此值
- cmin和cmax 标识在同一个事务中多个语句命令的序列值,从0开始,用于同一个事务中实现版本可见性判断
下面通过实验具体看看这些标记如何工作。在此之前,先创建测试表
CREATE TABLE test
(
id INTEGER,
value TEXT
);
开启一个事务,查询当前事务ID(值为3277),并插入一条数据,xmin为3277,与当前事务ID相等。符合上文所述——插入tuple时记录xmin,记录未被删除时xmax为0
postgres=> BEGIN;
BEGIN
postgres=> SELECT TXID_CURRENT();
txid_current
--------------
3277
(1 row)
postgres=> INSERT INTO test VALUES(1, 'a');
INSERT</