共计 1549 个字符,预计需要花费 4 分钟才能阅读完成。
这篇文章主要为大家展示了“PostgreSQL MVCC 源码的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让丸趣 TV 小编带领大家一起研究并学习一下“PostgreSQL MVCC 源码的示例分析”这篇文章吧。
MVCC 对每一个 DBA 来讲,都不陌生,即多版本控制(Multi-Version-Control)。正因为数据有了多个版本,才实现了读和写在一定程度上的分离,提高数据库每秒处理查询的能力(QPS)。
用户发起的普通查询请求(不包含 select … for update 语句),并不堵塞 DML 事务。在 Read Commit 事务隔离级别时,查询请求只读取查询请求之前已经提交的事务的数据更改,对当前版本的数据并不影响;
而 DML 语句,会操作当前版本。因此做到了读写分离的目的,提高数据库并发能力。
不同的数据库,实现 MVCC 的方法不同。Oracle 和 MySQL Innodb 存储引擎类似的使用 undo 来实现。
对于 PostgreSQL 数据库来讲,他没有 undo,那么,PG 又是怎么来实现他自己的 MVCC 呢?又有那些优缺点呢?
PG 用 copy tuple 和 tuple 的 xmin,xmax,cmin,cmax 等标记来实现多版本。
xmin:在创建记录 (tuple) 时,记录此时,后面每次 update 也会更新。
xmax: 在删除 tuple 或者 lock 时,记录此时;如果记录没有被删除,那么此时为 0。
cmin 和 cmax:主要为标识在同一个事务中多个语句命令的序列值。用于同一个事务中实现版本可见性判断。
1. 下面我们先来看一下 xmin 和 xmax 的变化:
从上图可以看出,4 条记录的 xmin 是一样的,都是“390689”,这说明是在同一个事务中创建的。另外 xmax 都为“0”,说明都没有被删除。cmin 和 cmax 都是 1,说明是同一个命令创建的。
接下来,我们 update 一下 id 为 1 的记录,看发生什么情况:
update 之后,并没有提交,重新开起另外一个窗口,查询:
我们看到,ID 为 1 的记录,只有 xmin 没有变化,其它三个值都发生了变化,其中 xmax 变成了”390691”。
然后我把事务提交掉,再在新窗口中查询:
我们看到,提交后,ID 为 1 的记录,xmin 变为“390691”,xmin 增加了 1;而 xmax 变成了 0。
从上面的案例中,我们从表面上可以看出,xmin 增加了。但是事实上,PostgreSQL 在底层所做的事情,远比这个要多。底层已经生成了一个新版本的 tuple,新版本 tuple 的 xmin 等于老版本的 xmax。
详细的 internal,我后面再展开讲。
2. 我们再来看一下 cmin 和 cmax 的变化:
我起一个事务,包含两条 update,一条 update ID 值为 2 的记录,一条 insert ID 值为 3 的记录:
事务“390694”中,cmin 和 cmax 的值,依次递增。从目前来看 cmin 和 cmax 实际上是同一个 field。
源码定义如下,用 union 实现了 CommandId,是一个 combo command id。
因此,从上面的例子来看,PostgreSQL 的 mvcc 实现是比较简单的。只需要通过对比 tuple header 中 xmin,xmax,cmin,cmax 与当前的 xid,就可以得到在 scan tuple 时,此 tuple 对于当前查询的可视性。
可见性判断逻辑:
但是也带来了另外一个问题:就是在没有 undo 的情况下,会导致空间的增长。因此 PostgreSQL 引入了 vacumm 后台进程,来定期清理这些 DEAD tuple。
以上是“PostgreSQL MVCC 源码的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道!