我读了一些材料,然后说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
在这种情况下,当单个update语句包含自定义函数时,它是否仍是原子的?
答案 0 :(得分:1)
好的,@ Schwern对Perl的了解可能是世界一流的,但是关于PostgreSQL事务,我可以纠正他:-)
PostgreSQL中的每条语句都在一个事务中执行,您可以自己开始/提交一个显式语句,也可以包含一个隐式语句。在声明的整个过程中,您将看到整个数据库的稳定视图。
如果您将myFunction
作为pl / pgsql中的数据库内自定义函数或类似的东西编写,那么它也将与调用它的语句处于同一事务中。如果它不运行自己的查询,只对它的参数进行运算,那么您就无需再考虑了。
如果您正在从函数中的表中进行读取,则需要对transaction isolation levels有所了解。特别是,请确保您了解“读取已提交”对于查看其他进程的活动意味着什么。
您所引用的博客文章正在讨论在数据库外部执行操作。它提出的解决方案正是您所要的-原子更新。
答案 1 :(得分:0)
函数调用中的update
,子查询和查询都应该看到一致的数据视图。
来自Chapter 13. Concurrency Control。
在内部,通过使用多版本模型(Multiversion Concurrency Control,MVCC)来维护数据一致性。 这意味着每个SQL语句都可以像以前一样看到数据快照(数据库版本),而与基础数据的当前状态无关。 查看并发事务在同一数据行上执行更新所产生的不一致数据,从而为每个数据库会话提供事务隔离。
我认为这意味着Postgres保留每个数据版本的每个语句。每个语句在整个运行过程中都会看到数据库的一致版本。其中包括子查询和函数调用。
这并不意味着您不必考虑并发性。这只是意味着update
将看到一致的数据。