2016-09-04 24 views
0

我需要鎖定一個用戶的行,以防止任何其他人更改內容。PostgreSQL - 如何在函數中創建關鍵部分

User A: call function lock_row() to lock row X 
User B: call function lock_row() to lock row X (lock cant be created and "exception" should be triggered as row X is already locked) 

當用戶A和B使用同一個會話連接時,情況並非如此。

因此,如何確保這樣的事情不會發生了:

User A: check if lock == 0 
User B: check if lock == 0 
User A: lock == 0 so SET lock = 1 
User B: lock == 0 is also here so SET lock = 1 

我想通過觸發的SQL語句不能直接創建鎖(上排UPDATE),而是功能,允許用戶釋放鎖出現意外錯誤。

如何創建「關鍵部分」?如何確保我函數中的關鍵部分能夠正確執行?

PostgreSQL版本9.x.

+0

https://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS –

+0

主要Postgres版本包括點後的第一個數字。沒有「9.x」版本,它是9.4或9.5等。 –

回答

0

所有你需要的是在同一個事務的獨家row lock
添加NOWAIT如果無法獲取鎖定(由另一個事務鎖定),使事務立即失敗。

BEGIN; 

SELECT 1 
FROM tbl 
WHERE tbl_id = x 
FOR UPDATE NOWAIT; 

- do something 

COMMIT; -- lock released automatically 

取決於你打算做的,限制較少FOR NO KEY UPDATE可能不夠好。

相關:

或者,你可以包裝SELECT或完整的交易成一個函數。同樣的效果。一個異常總是跳過整個事務(除非你陷入錯誤)。

諮詢鎖是另一種選擇,但不太可靠。當您可以通過行級鎖實現同樣的功能時,不需要回到這個通用工具。

+0

我可以使用它與休眠5? (或者只是創建我自己的SQL語句,我寧願避免) –

+0

@BartekSzczypien:我是Postgres的專家。不確定Hibernate。 –