2010-06-27 75 views
2

数据库中有表X和表的,BN,CN,DN,从X.订单查询(PostgreSQL的)锁

过程1个查询周期性地从X.

数据过程2继承的更新子表中的数据。例如,要更新表An和Bn,它会创建新的表Am和Bm,将数据加载到它们中,锁定访问专用An,Bn,并将An和Bn放入并更改Am和Bm以继承X.

问题是当进程1执行查询时(例如select * from X)它以共享模式锁定表An,Bn,Cn,Dn,并且锁定顺序未知。如果进程1锁定了Bn,那么进程2锁定我们有死锁。

有没有关于在postgresql查询锁定表的顺序(没有显式锁定)?或者可能有其他解决方案是可能的?

+0

SELECT不锁定表格,除非您明确要求锁定。你有没有检查pg_locks来看看发生了什么? http://www.postgresql.org/docs/8.4/interactive/view-pg-locks.html – 2010-06-28 06:28:01

+0

SELECT锁表(http://www.postgresql.org/docs/8.1/static/explicit-locking.html) ,并在我的情况下,它与专门请求删除的访问冲突。 访问共享 仅与ACCESS EXCLUSIVE锁定模式冲突。 SELECT和ANALYZE命令在引用的表上获取此模式的锁定。一般来说,任何只读取一个表并且不修改它的查询都会获得这种锁定模式。 – valodzka 2010-06-28 09:21:15

+0

它因为ACCESS EXCLUSIVE而发生冲突,那就是你的问题。 SELECT本身不是问题。 – 2010-06-28 11:08:14

回答

1

我知道你说的没有明确的锁定,但老实说你最好在这里下注显式锁定。由于这两个批次中的第一条语句都有一个lock命令来锁定您将使用的表。关于这一点最重要的部分是lock命令必须以相同的顺序锁定表,否则无论如何你会再次遇到死锁。

之后,确保两个批次的运行速度尽可能快,因为您正在使用表级别锁定...您不想再持有这些锁定时间。

+0

我简化了一下:进程1不是批处理作业,它是很多执行很多不同查询的处理程序。对每个查询使用显式锁定会非常烦人。 如果postgresql的顺序是可预测的,那么更改进程2的锁定顺序将会非常简单。 – valodzka 2010-06-27 21:07:41

+0

这就是为什么你不应该过分简化你的问题。尽管如此,选项仍然保持不变:要么执行显式锁定,要么处理失败时的死锁(因为postgres检测到死锁并杀死其中一个proclasses,因此另一个可以完成这是一个选项)。 – Donnie 2010-06-27 21:11:02

0

是否存在有关的查询 锁定表的顺序 PostgreSQL的任何信息(没有明确锁定)? 或者可能是其他解决方案是 可能吗?

正常情况下,postgresql的mvcc实现可以防止许多类型的死锁。有关更多详情,请参阅http://www.postgresql.org/files/developer/transactions.pdf

虽然,一个常见的解决方案是只处理死锁,也就是说,如果您的查询由于死锁而失败,请重试。