2014-01-07 20 views
9

我有一個表稱爲depositsPostgreSQL的鎖的控制時間等待

當存款製成,表被鎖定,所以查詢看起來是這樣的:

SELECT * FROM deposits WHERE id=123 FOR UPDATE

我認爲FOR UPDATE是鎖定表,以便我們可以操作它,而無需另一個線程跺腳數據。

雖然其他存款試圖獲取表的鎖,但會出現問題。發生什麼事情是,在鎖定桌子和撥打psql_commit()之間的某個地方發生了一些故障,並且鎖定了愚蠢的長時間。有一對夫婦的事情,我需要幫助解決:

  1. 試圖獲得鎖失靈的後續查詢,我試圖與NOWAIT實現這一點,但希望有一個超時方法(因爲它可能是確定等待,只是不等待一個'愚蠢的時間')

  2. 理想情況下,我會在通過這頭,並讓我的初始查詢只保持鎖定一段時間,這是可能與postgresql?

  3. 是否有一些其他的魔術功能,我可以在查詢(類似於NOWAIT),這將只有等待4秒鎖之前失敗?

  4. 由於代碼庫的痛苦單片面條代碼的性質,它不是簡單的一個不斷變化的全球CONFIGS的事,它有點需要一個每個基於查詢的解決方案

感謝您的幫助夥計們,我會繼續探索,但我沒有太多的運氣。這是PSQL的一個不存在的功能,因爲我發現這一點:http://www.postgresql.org/message-id/[email protected]

+0

定義「愚蠢的長」。另外:PostgreSQL版本?你的錯誤日誌中是否有任何PostgreSQL死鎖錯誤? –

+0

stupidly long = 30秒| 9.2.6是版本。 – FaddishWorm

+2

僅供參考,「死鎖」具有特定的含義:兩個交易,其中每個等待由另一個持有的鎖。PostgreSQL將檢測到這種情況並中止一個事務。你描述的情況不是一個僵局,而是一個無限期的等待。 –

回答

28

我認爲FOR UPDATE鎖定該表,這樣我們就可以對其進行操作,而不對數據另一個線程跺腳。

沒有。 FOR UPDATE只鎖那些行,以便在您的事務提交或回滾之前,嘗試鎖定它們的另一個事務(使用FOR SHARE,FOR UPDATE,UPDATEDELETE)會被阻塞。

如果你想要一個整體表鎖來阻止插入/更新/刪除,你可能想要LOCK TABLE ... IN EXCLUSIVE MODE

  1. 試圖獲得鎖失靈的後續查詢,我試圖與NOWAIT實現這一點,但希望有一個超時方法(因爲它可能是確定的等待,只是不等待「的愚蠢量時間')

    請參閱the lock_timeout setting。這是在9.3中添加的,並且在舊版本中不可用。

    使用statement_timeout可以實現舊版本的粗略近似值,但這可能會導致語句被不必要地取消。如果statement_timeout爲1秒,並且語句在鎖上等待950ms,則它可能會獲取鎖並繼續執行,但只能立即通過超時取消。不是你想要的。

    有沒有查詢級的方式來設置lock_timeout,但你可以只應該:

    SET LOCAL lock_timeout = '1s';

    BEGIN交易之後。

  2. 理想情況下,我會在通關處關閉它,並讓我的初始查詢只鎖定一段時間,這是否可以通過postgresql?

    有一個聲明超時,但鎖在交易電平。沒有事務超時功能。

    如果您正在運行單語句事務,則可以在運行語句前設置statement_timeout以限制其運行時間。然而,這與限制鎖的持續時間並不完全相同,因爲它可能會等待鎖的允許1秒的900毫秒,只能實際保持鎖100毫秒,然後通過超時取消。

  3. 是否有一些其他的魔術功能,我可以加上查詢(類似於NOWAIT),它只會在失敗之前等待鎖定4秒?

    號您必須:

    BEGIN; 
    SET LOCAL lock_timeout = '4s'; 
    SELECT ....; 
    COMMIT; 
    
  4. 由於代碼庫,它不單純是一個不斷變化的全球CONFIGS的物質的痛苦單片面條代碼的性質,它有點需要一個基於查詢的解決方案

    SET LOCAL對此適用且優選。

    在查詢文本中沒有辦法做到,它必須是一個單獨的語句。

    鏈接到的郵件列表發佈是針對從未實現的假想語法(至少在公開的PostgreSQL版本中)並且不存在的提議。

在這種情況下,您可能需要考慮「樂觀併發控制」,通常稱爲「樂觀鎖定」。它以更高的查詢重複率和更多應用程序邏輯的需求爲代價,使您可以更好地控制鎖定行爲。

+2

我在堆棧溢出中看到的最佳答案之一 - 謝謝堆! – FaddishWorm

+2

更新:Postgres 9.5將'SKIP LOCKED'選項與現有的'NOWAIT'選項一起添加到'SELECT ... FOR UPDATE'。文檔:使用SKIP LOCKED,可以跳過任何不能立即鎖定的選定行。跳過鎖定的行提供了不一致的數據視圖,因此這不適合用於通用目的,但可用於避免鎖定與多個使用者訪問類似隊列表的爭用。 –

+0

你從哪裏找到像'10s'這樣的語法?它在文檔中聲明lock_timeout接受整數... – asm0dey