2016-07-26 64 views
1

我有一個回調機制,基本上從給定匹配條件的表中獲取一行,執行一些操作並基於行記錄中的刪除標記刪除該行。防止同時讀取Oracle中的行

問題是在此係統中可能有多個具有相同匹配標準的併發回調。我想實現的是,在第一次回調中,當我選擇要處理的行時(基於刪除標誌,此行可能會在處理後被刪除或不刪除),我希望其他回調等待。換句話說,我想在表的一行上有一個讀鎖,如果在第一個回調中確實刪除了第二個回調,那麼第二個回調沒有任何用處,它應該通過。

我在這裏使用JDBC來完成這些操作。

回答

3

您可以使用the for update clause鎖定您選擇的行。嘗試檢索相同行的第二個會話(其中也包含for update)將默認處於阻止狀態,直到您釋放鎖定爲止,方法是提交或回滾。

所以會話1的作用:

select column1, column2, ... from your_table where ... for update; 

並且可以處理結果。雖然這樣做會話2也會這樣做:

select column1, column2, ... from your_table where ... for update; 

但現在會阻塞,直到會話1釋放鎖。

作爲一個簡單的演示,讓有一張小桌子:

create table t42 (id number, delete_flag varchar2(1)); 
insert into t42 values (1, 'N'); 
insert into t42 values (2, 'N'); 
insert into t42 values (3, 'Y'); 

commit; 

在會議1:

SQL> select * from t42 where delete_flag = 'Y' for update; 

     ID D 
---------- - 
     2 Y 
     3 Y 

在會議2:

SQL> select * from t42 where delete_flag = 'Y' for update; 

...這只是坐在在那裏等着。早在會議1

,刪除你的處理將行之一:

SQL> delete from t42 where id = 2; 

1 row deleted. 

會話2仍然在等待。讓我們說出於某種原因,你只想刪除那一行,並把另一行留在那裏,這樣回調事務就完成了。現在,在會話1:

SQL> commit; 

Commit complete. 

馬上會議2現在報告:

 ID D 
---------- - 
     3 Y 

當鎖被釋放查詢被重新執行,所以它認爲當前提交的數據,而不是(鎖定)提交命令時存在的數據。

會話2現在對該行具有鎖定,並且其他會話仍將被阻止,等待會話會話提交或回滾。如果會話1刪除了它已經鎖定的兩行,會話2將會看到'沒有選擇行',並且沒有行鎖(儘管它仍然會阻止表被刪除或截斷)。

這不完全是讀取鎖 - 其他會話仍然可以查詢表,包括鎖定的行,只要它們沒有for update子句。但只要你所有的回調都在做同樣的事情,他們應該按照你的意願行事。

1

我認爲您正在尋找一個Select For Update Cursor。 第一個閱讀器會阻止其他閱讀器(如果包含NOWAIT子句,其他會話將不會等待)