并发选择条件插入/更新/删除 - PostgreSQL

Art*_*hur 5 postgresql concurrency

我有一个intervals表,用于存储变量的start日期和end日期variable_id(四列:)id, start, end, variable_id

客户端计算一个变量的新间隔并将它们存储在该表中。为了保持一致性(对于variable_id我不想间隔重叠),客户端首先检查(select),我们有什么样的时间间隔,然后insertdelete和/或update相应的(或者什么都不做)。

如果两个客户同时这样做,当然会有我插入重叠间隔的风险,这是我不想要的。

其实我的问题很简单:我该怎么办?

似乎 aSELECT .. FOR UPDATE不起作用,因为这会锁定现有的行,这对我来说还不够,因为可能会插入行。我宁愿需要“ SELECT * FROM intervals WHERE variable_id = 1234”的结果在某种程度上是“安全的”。

我已经实现了一个使用SERIALIZABLE事务的解决方案。结果是,如果两个客户端输入这个 select/update-delete-insert 事务,一个将失败(could not serialize access due to read/write dependencies among transactionscould not serialize access due to concurrent update),在这种情况下,我只需要再次运行我的 select/update-delete-insert 逻辑以尝试插入更合适的间隔.

这里的问题是serializable事务似乎锁定了整个表。但是如果一个客户端想要更新变量1234的间隔,而另一个客户端想要更新变量4321的,应该没有问题,两个事务应该能够愉快地运行。

我不是 SQL 专家,甚至无法确定这是一个简单的经典 sql 问题还是一个难题。

一些评论:

  • PostgreSQL 9.1.1
  • 交易中实际上还有很多事情要做。我不仅更新了间隔,而且还在另一个表中插入了相应变量的值。在间隔intervals表上,我们有变量的值的时间间隔。但是,我认为这不会干扰上述问题。

kgr*_*ttn 8

关于 SERIALIZABLE 事务,请务必注意本节底部附近的“以获得最佳性能”提示:http : //www.postgresql.org/docs/9.1/interactive/transaction-iso.html#XACT-SERIALIZABLE 这些可以显着降低回滚率。

也就是说,并不是为了阻止使用 SERIALIZABLE 事务隔离级别,您所描述的听起来正是 EXCLUSION CONSTRAINT 旨在解决的那种问题。在存在强制执行业务规则的声明性约束的情况下,这几乎总是比使用命令式编码(在触发器或应用程序代码中)更好。

http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION

http://www.postgresql.org/docs/9.1/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE

要将此功能与日期一起使用,您目前需要使用 TEMPORAL 模块:

http://pgfoundry.org/projects/temporal/

当您迁移到 PostgreSQL 9.2 版(预计将于今年夏天发布)时,您可能希望将 TEMPORAL 列迁移到 RANGE。9.2 RANGE 特性、TEMPORAL 数据类型和 EXCLUSION CONSTRAINT 特性都是 Jeff Davis 解决问题中提出的问题的所有工作。它们旨在协同工作。

完全披露:9.1 中的 SERIALIZABLE 事务行为是由我和麻省理工学院的 Dan RK Ports 开发的。