原文链接:http://blog.chinaunix.net/uid-20726500-id-4040024.html
事务的实现原理可以解读为DBMS采取何种技术确保事务的ACID特性。PostgreSQL针对ACID的实现技术如下表所示。
表1:事务的4个特征ACID及响应的实现技术
ACID |
实现技术 |
原子性 |
MVCC |
一致性 |
约束(主键,外键等) |
隔离性 |
MVCC |
持久性 |
WAL |
可以看到PostgreSQL中支撑ACID的主要是MVCC和WAL两项技术。MVCC和WAL是两个比较成熟的技术,通常的关系数据库中都有相应的实现,但每个数据库具体的实现方式又存在很大差异。下面介绍一下PostgreSQL中MVCC和WAL的基本实现原理。
1. MVCC
MVCC(Multiversion Concurrency Control)即多版本并发控制,它可以避免读写事务之间的互相阻塞,相比通常的封锁技术可极大的提高业务的并发性能。PostgreSQL中的MVCC实现原理可简单概括如下:
1)数据文件中存放同一逻辑行的多个行版本(称为Tuple)
2)每个行版本的头部记录创建以及删除该行版本的事务的ID(分别称为xmin和xmax)
3)每个事务的状态(运行中,中止或提交)记录在pg_clog文件中
4)根据上面的数据并运用一定的规则每个事务只会看到一个特定的行版本
通过MVCC读写事务可以分别在不同的行版本上工作,因此能够在互不冲突的情况下并发执行。
图1:基于MVCC的数据更新举例
2. WAL
当系统意外宕机后,恢复时需要回退未完成事务所做的更改并确保已提交事务所作的更改均已生效。在PostgreSQL中通过前面提到的MVCC很容易做到的第一点,只要把所有pg_clog文件中记录的所有“运行中”的事务的状态置为“中止”即可,这些事务在宕机时都没有结束。对于第二点,必须确保事务提交时修改已真正写入到永久存储中。但是直接刷新事务修改后的数据到磁盘是很费时的,为解决这个问题于是引入了WAL(Write-Ahead Log)。
WAL的基本原理如下:
1)更新数据页前先将更新内容记入WAL日志
2)异步刷新数据Buffer的脏页和WAL Buffer到磁盘
3)Buffer管理器确保绝不会先于对应的WAL记录刷新脏数据到磁盘
4)事务提交时,将WAL日志同步刷新到磁盘
5)Checkpoint发生时,将数据Buffer的所有脏页刷新到磁盘
图2:数据更新时的Buffer修改
图3:更新提交和Checkpoint时的磁盘同步