如何防止在运行PostgreSQL的非原子计算,同时多个客户端更新异常?

问题描述 投票:0回答:1

我正在使用复制(1个主,从站2),其是由两个单独的服务器访问3个的PostgreSQL实例:

  • 第一(未曝光)服务器中的每一行基本上遍历在一个特定的表和不断更新为每个用户特定的列(资源)每刻度(基于这些资源的生产速度)。
  • 第二服务器是一个公共API暴露各种功能,例如花费一定量的这些资源。

为了访问和操纵数据,我使用ORM库,让我写出如下代码:

const resources = await repository.findById(1337);
// some complex computation
resources.iron = computeNewIron(resources.iron);
await repository.save(resources);

当然,它可能出现的API要扣除资源的权利,当服务器处理蜱试图更新资源,这可能会导致无论是服务器承担了一定的资源是不正确量的具体金额,基本上典型的更新异常。

我的问题是,我不只是写一个“简单”原子查询等UPDATE table SET iron = iron + 42 WHERE id = :id。在ORM库在内部使用直接分配未自引用这将产生一个类似于UPDATE table SET iron = 123 WHERE id = :id其中所述的用量先前已计算出的各列。

我只能假定它是能够避免提及异常,如果我使用的递增/自引用原子递减值手动编写查询。我想知道哪些其他选项可以缓解这个问题。我应该换我SELECT /运算/ UPDATE的事务?这是否足够?

database postgresql transactions concurrentmodification
1个回答
1
投票

你的问题是有点不清楚,但如果你的交易跨越多个报表,但需要有数据库的一致状态,基本上有两种选择:

  1. 使用悲观锁:当你从数据库中读取值,与SELECT ... FOR UPDATE做到这一点。那么行会被锁定为您的交易时间,并没有并发事务可以修改它们。
  2. 使用乐观锁定:在REPEATABLE READ隔离级别开始您的交易。然后你看到数据库的一致性快照为您的交易的整个过程中。如果有人你看他们后其他人修改你的数据,你UPDATE将导致序列化错误,你将不得不重试事务。

乐观锁是更​​好,如果冲突是罕见的,而悲观锁是最好,如果冲突是可能的。

© www.soinside.com 2019 - 2024. All rights reserved.