从两个表中读取时的完整性:订单和order_items

时间:2015-06-05 10:37:39

标签: database postgresql transactions

我正在寻找一种在从数据库读取时实现数据完整性的方法(希望不会使用大量资源),而无需在架构中添加新字段。

完整性是指订单表中订单总和与订单商品价格总和之间的完整性:

orders (id PK, description text, amount decimal)
order_items (id PK, order int ref orders.id, item int ref items, price decimal)
items (id PK, description text)

重要的是order_items的数量可能非常大(数千),并且每次显示完整的订单金额时读取所有订单都不太实际。但是当导出订单时,它应该是正确的,即使它可以在同一时刻更新。

例如:

  1. 用户A开始导出订单。
  2. 系统读取订单详细信息:SELECT * FROM orders WHERE id = 42
  3. 用户B开始更新订单#42,以便添加新订单商品并更新订单金额(在交易中,因此数据库中的数据是连贯的)。
  4. 系统继续执行第二个请求,以便在完成导出请求时订购详细信息:SELECT * FROM order_items WHERE order = 42
  5. 现在导出的数据并不一致,因为订单总金额与通过汇总order_items获得的金额不匹配。
  6. 在导出时打开事务或者在读取它们之前锁定两个表是否更好?

    数据库是PostgreSQL。

    顺便说一句,这个问题应该是非常基础的,所以请为重复道歉,我尽力搜索解决方案,但未能找到明确的解决方案。

1 个答案:

答案 0 :(得分:1)

你需要取一杯好的热茶和咖啡,然后阅读transaction isolation上的页面。

有两种选择。在第一种情况下,假设您锁定表以防止写入。然后,只要B在单个事务中执行更新,那么“read committed”就可以了。您不会在任何时候看到一半的更新。

在第二种情况下,“可重复读取”隔离级别将再次确保,只要B在单个事务中进行更新,那么一切都会很好。 A看到数据库的“快照”将在它开始交易时固定。

当然,能够更新已导出的订单可能没有意义(因为可能有人已经尝试打包并发送我的原始订单)。我猜测订单/订单商品可能就是一个例子。

(回答编辑,因为Radek的评论表明我不清楚,如果你需要解决并发问题,那么很明显。希望现在就是这样)