3

我在 Windows 环境中使用 PostgreSQL 9.2。我在使用 MSDTC的 2PC( 2 阶段提交)环境中。

我有一个客户端应用程序,它在 SERIALIZABLE 隔离级别启动事务,在表中为特定外键值插入新的数据行(列上有一个索引),并投票完成事务(交易已准备好)。事务将由事务协调器提交。

紧接着,在事务之外,同一个客户端向所有行请求这个相同的特定外键值。

因为在前一个事务真正提交之前可能存在延迟,所以 SELECT 子句可能会返回数据的前一个快照。事实上,它确实有时会发生,这是有问题的。当然,应用程序可能会重新设计,但在那之前,我正在寻找锁定解决方案。咨询锁?

我已经在对特定行执行 UPDATE 时解决了这个问题,然后使用 SELECT...FOR SHARE,它运行良好。SELECT 等待事务提交并返回新旧行。

现在我正在尝试为 INSERT 解决它。SELECT...FOR SHARE 不会立即阻止并返回。

这里没有并发问题,因为只有一个客户端处理一组特定的行。我已经知道 MVCC。

任何帮助表示赞赏。

4

1 回答 1

1

要等待尚未提交的INSERT,您需要使用谓词 lock。PostgreSQL 中对可序列化支持的谓词锁定有限,但它不会直接暴露给用户。

简单的SERIALIZABLE隔离在这里对您没有帮助,因为SERIALIZABLE只需要有一个事务可能发生的顺序来产生一致的结果。在您的情况下,此顺序SELECT后跟INSERT.

我能想到的唯一选择是在ingACCESS EXCLUSIVE之前锁定桌子。INSERT这只会在COMMIT PREPAREDROLLBACK PREPARED时间被释放,同时任何其他查询都将等待锁定。您可以通过BEFORE触发器强制执行此操作,以避免更改应用程序的需要。但是,如果您这样做,您可能会遇到奇怪的死锁和回滚,因为INSERT将获得较低的锁,然后您将尝试在触发器中进行锁升级。如果可能最好LOCK TABLE ... IN ACCESS EXCLUSIVE MODE在.INSERT

正如您所提到的,这主要是一个应用程序设计错误的问题。期望看到尚未提交的行并没有任何意义。

于 2013-07-08T11:43:23.070 回答