我在Ubuntu 15.10和Freebsd上使用PHP 7(5.6.11)和postgresql 9.4。
我的代码从表中选择带有“for update”选项的id的单行。 有时(一个数百个)这个查询执行很长时间,大约20-90秒。我的代码工作在大约30个线程中。
据我所知,“select * from table for update”只锁定表中的单行,只有当另一个进程已经选择了这一行时我才能得到这样的行为。我是对的吗?但它不会发生,因为脚本只有在从消息代理获取消息后才会执行。
单行的单条消息。所以我无法想象谁和为什么可以阻止这一行。 (select * from table for update
在一个地方使用,我从队列中获取消息。)
我尝试使用来自pg_locks和ps ax输出的信息。我在选择更新之前保存此信息然后,如果我抓住长查询,我会在日志中发送此信息。我看到锁定表的进程的pid,但我没有在ps ax输出中看到这个pid。这让我很困惑。
有没有人有任何想法?
答案 0 :(得分:0)
我找到了理由。我使用自己的任务管理器与ActiveMQ一起工作。有时由于某些原因,任务管理器会为某些任务设置暂停。然后,在某个事件之后,任务取消暂停并重新发送到队列中。重新发送包装在数据库和ActiveMQ事务中。
对于使用ActiveMQ,我使用此库:https://github.com/centraldesktop/php-stomp
对于发送消息,我使用同步模式,我发现,我忘了使用此模式进行交易。因此,当任务在队列中重新发送时,第一条消息在没有事务的情况下进入队列,它们运行脚本......并且这些脚本应该等到resender完成重新发送任务并提交数据库事务。
答案 1 :(得分:-1)
不同的数据库产品使用截然不同的锁定机制。有些人在执行select * from table for update where id=34
时可能会锁定一行或一个块。您需要阅读官方文档。
如果您在没有任何条件的情况下执行select * from table for update
,则会锁定整个表格,直至commit
或rollback