簡體   English   中英

鎖定行,直到下一個選擇postgres

[英]lock the rows until next select postgres

在postgres中有沒有一種方法可以鎖定行,直到同一系統中的下一個選擇查詢執行為止。 還有一件事是,鎖定的行將沒有更新過程。 場景是這樣的

如果table1包含如下數據

id |    txt
-------------------
1 |    World 
2 |    Text
3 |    Crawler
4 |    Solution
5 |    Nation
6 |    Under
7 |    Padding
8 |    Settle
9 |    Begin
10 |    Large
11 |    Someone
12 |    Dance

如果sys1執行

select * from table1 order by id limit 5;

那么對於同時執行select語句的其他系統,它應該將ID從1到5的行鎖定。

稍后,如果sys1再次執行另一個選擇查詢,例如

select * from table1 where id>10 order by id limit 5;

然后應該釋放以前鎖定的行。

我認為這是不可能的。 您不能阻止對表的只讀訪問(除非選擇已完成FOR UPDATE

據我所知,您唯一的機會就是使用pg_advisory_lock()函數。
http://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS

但是,這需要“手動”釋放通過它獲得的鎖。 這樣您將不會獲得自動解鎖。

要鎖定行,您將需要以下內容:

select pg_advisory_lock(id), * 
from 
( 
  select * table1 order by id limit 5
) t

(請注意在LIMIT部分使用派生表。請參閱我發布的手冊鏈接以獲取解釋)

然后,您需要存儲檢索到的ID,然后為每個ID調用pg_advisory_unlock()

如果每個進程總是一次釋放所有 ID,則可以簡單地使用pg_advisory_unlock_all() 然后,您將不需要存儲檢索到的ID。

請注意,這不會阻止其他人使用“正常”選擇讀取行。 僅當訪問該表的每個進程使用相同的獲取鎖的模式時,它才起作用。

看起來您確實有一個超越數據庫邊界的事務,並且所有更改都發生在另一個系統中。

我的想法是select ... for update no wait鎖定相關行,然后將數據卸載到另一個系統中,然后rollback以解鎖行。 沒有兩個select ... for update查詢的select ... for update將選擇同一行,第二個select將立即失敗,而不是等待並繼續。

但是您似乎並沒有以任何方式標記卸載的記錄。 我不明白為什么兩個不連續的選擇不會愉快地選擇重疊范圍。 因此,我仍然會使用標志和/或目標用戶名來update記錄,並且只會選擇未設置標志的記錄。

我同時嘗試了select ... for updatepg_try_advisory_lock並設法接近我的要求。

/*rows are locking but limit is the problem*/
select * from table1 where  pg_try_advisory_lock( id) limit 5;
.
.
$_SESSION['rows'] = $rowcount; // no of row to process
.
.
/*afer each process of word*/
$_SESSION['rows'] -=1;
.
.
/*and finally unlock locked rows*/
if ($_SESSION['rows']===0)
select pg_advisory_unlock_all() from table1

但是這有兩個問題
1.由於限制將在鎖定之前應用,因此每次相同的行嘗試在不同的實例中鎖定時。
2.不確定pg_advisory_unlock_all將解鎖當前實例或所有實例鎖定的行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM