【问题标题】:Can I rely on it that every single update statement in postgresql is atomic?我可以相信 postgresql 中的每个更新语句都是原子的吗?
【发布时间】:2019-02-28 20:52:57
【问题描述】:

在说postgresql中的每个更新语句都是原子的之前,我阅读了一些资料。

例如,

update set column_1 = column_1 + 100 where column_2 = 10;

即使我有多个进程同时调用更新,我也可以相信它们会按顺序发生,因为每个更新都是在幕后进行的,并且“read_modify_write”循环被封装在一个包中。

但是,如果更新语句如下所示:

update set column_1 = myFunction(column_1) where column_2 = 10;

这里,myFunction() 是我创建的一个存储过程。在这个函数中,我将根据它的数量对 column_1 应用不同的数学运算。比如:

    if(column_1 < 10):
            // do something
    else if (column_1 < 20):
            // do something
    else
            // do something

在这种情况下,当单个更新语句包含自定义函数时,它是否保持原子性?

【问题讨论】:

  • 您可以通过将其放入事务中来避免不确定性。
  • @Schwern 但是我应该交易哪个区块?围绕更新声明?喜欢开始;更新集 column_1 = myFunction(column_1) where column_2 = 10;提交;?
  • @JaneL 需要原子化的部分。这看起来像update,是的。这将包括update 所做的任何事情,例如子查询和函数。
  • @Schwern 我之前想过这个解决方案,但是一篇文章让我担心。 blog.2ndquadrant.com/… 在`事务不阻止这种情况吗? ` 部分,它甚至表示 BEGIN;/COMMIT;不能防止读-修改-写并发竞争。我不确定这是怎么发生的。
  • 单个语句始终是原子的。它始终会看到语句开始时数据库的一致快照 - 包括语句内部使用的任何函数或它可能使用的子查询。

标签: postgresql concurrency parallel-processing database-concurrency


【解决方案1】:

好的,@Schwern 对 Perl 的了解可能是世界一流的,但关于 PostgreSQL 事务,我可以纠正他 :-)

PostgreSQL 中的每条语句都在一个事务中执行,要么是您自己开始/提交的显式语句,要么是包装语句的隐式语句。在语句执行期间,您将看到整个数据库的稳定视图。

如果您将myFunction 写为 pl/pgsql 或类似的数据库内自定义函数,那么它也将与调用它的语句在同一个事务中。如果它不运行自己的查询,只是对其参数进行操作,那么您无需进一步考虑。

如果您在函数中读取表格,那么您将需要熟悉transaction isolation levels。特别是,请确保您了解“已提交读取”对于查看其他进程的活动意味着什么。

您参考的博客文章正在讨论在数据库之外执行操作。它提出的解决方案正是您要问的 - 原子更新。

【讨论】:

  • 首先我要承认,我不是 Postgres 专家。对我的回答有任何反馈吗?
【解决方案2】:

函数调用中的update、子查询和查询都应该看到一致的数据视图。

来自Chapter 13. Concurrency Control

在内部,通过使用多版本模型(Multiversion Concurrency Control,MVCC)来维护数据一致性。 这意味着每个 SQL 语句都会看到一段时间前的数据快照(数据库版本),而不管基础数据的当前状态如何。查看并发事务对相同数据行执行更新产生的不一致数据,为每个数据库会话提供事务隔离。

我相信,这意味着 Postgres 会为每条语句保留一个数据版本。每个语句在其整个运行过程中都看到数据库的一致版本。这包括子查询和函数调用。

这并不意味着您不必考虑并发性。这只是意味着update 将看到一致的数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多