2016-03-25 24 views
0

我在Ubuntu 15.10和Freebsd上使用PHP 7(5.6.11)和postgresql 9.4。如何檢測爲什麼鎖錶行?

我的代碼從表格中選擇單行,帶有「for update」選項。 有時(一個數百個)這個查詢執行很長時間,大約20-90秒。我的代碼在大約30個線程中工作。

據我所知,「select * from table for update」只鎖定表中的單個行,並且只有在另一個進程已經選擇了該行時,我才能獲得這樣的行爲。我對嗎?但它不能發生,因爲腳本只有在從消息代理獲取消息後才執行。

單行消息。所以我無法想象誰和爲什麼可以阻止這一行。 (在一個地方使用select * from table for update,我從隊列中獲取消息)。

我嘗試使用來自pg_locks和ps ax輸出的信息。在選擇更新之前,我保存這些信息,然後,如果我發現長時間查詢,我會在日誌中發送此信息。我看到進程鎖定表的PID,但我沒有看到在ps ax輸出這個PID。這讓我困惑。

有沒有人有任何想法?

+0

您將需要爲此提供文檔。假設這是此時「暫停」的唯一查詢,那麼它確實聽起來像鎖定。但是,我從來沒有聽說過沒有列入pg_locks中的鎖。 –

回答

0

我找到了原因。我使用與ActiveMQ一起工作的自己的任務管理器。有時出於某種原因,任務管理器會爲某些任務設置暫停。然後,在某些事件發生後,任務將被解除並重新排隊。重新發送包裝在數據庫和ActiveMQ事務中。

對於ActiveMQ的工作中,我使用這個庫:https://github.com/centraldesktop/php-stomp

要發送的郵件,我使用同步模式,我發現,我忘了使用該模式進行交易。所以當任務在隊列中重新發送時,第一條消息進入隊列而沒有事務,它們運行腳本並且......這些腳本應該等到重新發送完成後重新發送任務並提交他的數據庫事務。

-1

不同的數據庫產品使用截然不同的鎖定機制。有些人,當你做一個select * from table for update where id=34可能會鎖定一行或一個塊。你需要閱讀官方文檔。

如果你做一個select * from table for update沒有任何標準,你會鎖定整個表,直到你commitrollback

+0

我檢查了這一點,我的請求通過在postgresql中的id鎖定了唯一的一行。 – Hayate