2011-10-19 46 views
2

比方說,我有類似下面的代碼:如何在選擇鎖定,不只是插入/更新/刪除

begin 
    select ... from T where x = 42;   -- (1) 
    . 
    . 
    . 
    update T ... where x = 42;    -- (2) 
    commit; 
end; 

我是在說,由(2)執行時是正確的,有什麼在T被選擇(1)可能不再是T,如果,例如,在另一會話執行下列執行:

delete from T where x = 42; 

如果是這樣,我想發生這樣的select語句「鎖'T,所以它不能被修改。

我知道我可以通過做明確地做到這一點:

lock table T in exclusive mode; 

但如果T一種觀點?我一定要看看通過T觀/子視圖的定義,找到它引用的所有表和單獨鎖定它們,或者我可以做這樣的事情:

begin 
    START_TRANSACTION; 
    select ... from T where x = 42;   -- (1) 
    . 
    . 
    . 
    update T ... where x = 42;    -- (2) 
    commit; 
end; 

START_TRANSACTION確保鎖定所有表中提到的所有選擇語句直到交易完成?

或者是否有另一個更好的解決這個問題?如果這很重要,我正在使用Oracle 10g。

+1

您需要'SELECT ... FOR UPDATE'來鎖定您從表中讀取的行。仔細閱讀有關隔離級別和事務的所有信息。 –

回答

0

我很確定交易正是你想要的。該幫助爲一系列操作實施了所謂的ACID

2

您需要使用select ... for update變化,如here所示。

你絕對是不要想要鎖定整個表,儘管鎖定一個視圖是有效的。來自Oracle docs

當在視圖上發出LOCK TABLE語句時,基礎基表被鎖定。

然而,這可能是一個性能殺手,你的數據庫管理員找到你 - 有藏身之地:-)

5

我是在說,由(2)執行時是正確的,從(1)中的T中選擇的 無論如何都可能不在T中

是的。

所以,你可以通過做鎖定該行...

SELECT ... 
[INTO ...] 
FROM T 
WHERE x = 42 
FOR UPDATE [NOWAIT]; 

您可以選擇使用NOWAIT做,如果別人已經鎖定了這一行的聲明失敗。如果沒有NOWAIT,語句會暫停,直到它可以鎖定該行。

+0

'NOWAIT'?你確定你想要嗎? – paxdiablo

+0

已更改。複製出一些舊代碼,直到你指出它才考慮它。謝謝。 – cagcowboy

相關問題