ITPub博客

首页 > > > MVCC的PostgreSQL并发

MVCC的PostgreSQL并发

作者:zuike2000 时间:2020-02-20 15:03:26 0 删除 编辑

Postgres的一大卖点是它如何处理并发。承诺很简单:读取永远不会阻止写入,反之亦然。Postgres通过一种称为“多版本并发控制”的机制来实现这一目标。这种技术不是唯一的Postgres的:有实现某种形式的MVCC,包括Oracle,Berkeley DB的,CouchDB的和几个数据库等等。在PostgreSQL上设计高度并发的应用程序时,了解在Postgres中如何实现MVCC非常重要。实际上,它是解决难题的非常优雅且简单的解决方案。

MVCC如何运作

postgres中的每个事务都有一个名为XID的事务ID。这包括单个语句事务,例如插入,更新或删除,以及通过BEGIN- 显式地将一组语句包装在一起COMMIT。事务开始时,Postgres会递增XID并将其分配给当前事务。Postgres还在系统中的每一行上存储交易信息,该信息用于确定该行是否对交易可见。

例如,当您插入一行时,postgres会将XID存储在该行中并调用它xmin。xmin该事务对已提交且其小于当前事务的XID的每一行都是可见的。这意味着您可以启动一个事务并插入一行,直到该事务COMMIT对该行不可见。提交并创建其他事务后,他们将能够查看新行,因为它们满足xmin < XID条件-并且创建该行的事务已完成。

DELETEs和UPDATEs 发生类似的机制,仅在这些情况下,Postgres xmax在每一行上存储一个值以确定可见性。此图显示了两个并发事务插入和读取行,以及MVCC如何在事务隔离方面发挥作用。

对于以下图表,假定以下DDL:

CREATE TABLE numbers (value int);



虽然xmin和xmax值在日常操作中是隐藏的,但是您实际上可以只要求它们,而Postgres会很乐意将它们提供给您:

SELECT *, xmin, xmax FROM numbers;

您还可以很容易地获得当前事务的XID:

SELECT txid_current();

整齐!

我知道您在想什么:两个事务同时更新同一行呢?这就是进入事务隔离级别的地方。Postgres基本支持两种模型,这些模型使您可以控制这种情况的处理方式。默认值,READ COMMITTED在初始事务完成后读取该行,然后执行该语句。如果行在等待时发生更改,则基本上会重新开始。例如,如果发出UPDATE带有WHERE子句的,则该WHERE子句将在初始事务提交后重新运行,并且UPDATE如果WHERE仍然满足该子句,则会执行该子句。这是两个事务修改一行的示例,其中初始UPDATE引起WHERE第二个事务的子句不返回任何行。因此,第二笔交易根本不会更新任何行:



如果需要对此行为进行更好的控制,可以将事务隔离级别设置为SERIALIZABLE。使用这种策略,上述情况将只会失败,因为它表示“如果我要修改的行已被另一个事务修改,甚至不要尝试,”并且Postgres将以错误消息响应ERROR: could not serialize access due to concurrent update。由您的应用程序来处理该错误并重试,或者如果这是合理的话则放弃。



MVCC的缺点

现在您知道了MVCC和事务隔离的实际工作原理,您已经添加了另一个工具来解决SERIALIZABLE隔离级别很方便的问题。MVCC的优点显而易见,但也有一些缺点。

由于不同的事务对不同的行集具有可见性,因此Postgres需要维护潜在的过时记录。这就是为什么UPDATE实际上创建一个新行以及为什么DELETE不真正删除该行的原因:它只是将其标记为已删除,并适当地设置了XID值。事务完成后,数据库中将有一些行可能对以后的任何事务都不可见。这些被称为死行。MVCC带来的另一个问题是,交易ID只能增长得如此之多–它们是32位,只能“支持”大约40亿笔交易。当XID达到最大值时,它将环绕并从零开始。突然间所有 这些行似乎在将来的交易中,并且没有新的交易对这些行具有可见性。

死行和事务XID环绕问题都可以通过来解决VACUUM。这应该是例行维护,但值得庆幸的是Postgres带有一个auto_vacuum守护程序,它将以可配置的频率运行。注意这一点很重要,因为在真空频率方面,不同的部署会有不同的需求。您可以阅读有关Postgres文档VACUUM上实际执行的操作以及Heroku如何处理的更多信息。

原文作者:;如有侵权,请联系管理员删除。

上一篇: online DDL
请登录后发表评论 登录
全部评论

注册时间:2019-04-16

  • 博文量
    404
  • 访问量
    2062