2009-09-28 96 views
2

有沒有辦法在Oracle(10g)中專門鎖定表格進行閱讀?我對Oracle不是很熟悉,所以我問DBA,他說在Oracle中鎖定一張表是不可能的?Oracle 10g上的獨佔表(讀)鎖?

我實際上在尋找像SQL Server(TABLOCKX HOLDLOCK)這樣的提示。

編輯

在迴應一些問題的答案:我需要鎖定表的讀數是實現能夠被多個客戶端讀取隊列的原因,但它應該爲2是不可能的客戶讀取相同的記錄。那麼,實際情況是:

  1. 鎖表
  2. 隊列
  3. 閱讀下一個項目
  4. 從隊列中刪除項目
  5. 刪除表鎖

也許有這樣做的另一種方式(更有效率)?

+2

我有相反的情況:我瞭解Oracle,但對SQL Server不太瞭解。 「鎖定桌子閱讀」是什麼意思?你想阻止什麼發生? – APC 2009-09-28 15:16:59

回答

14

如果你只是想阻止修改數據的任何其他會話可以發出

LOCK TABLE whatever 
/

這阻止更新數據其他會話,但我們不能從閱讀它阻止其他peple。

請注意,在Oracle中,這種表鎖定很少需要,因爲Oracle運行讀取一致性策略。這意味着如果我們運行一個需要15分鐘運行的查詢,返回的最後一行將與第一行一致;換句話說,如果結果集按照相反的順序排序,我們仍然可以看到完全相同的行。

編輯

如果你想實現一個隊列(實際上並沒有使用Oracle的built-in Advanced Queueing functionality),那麼SELECT ... FOR UPDATE是要走的路。該構造允許一個會話選擇並鎖定一行或多行。其他會話可以更新未鎖定的行。然而,除非你使用11g,否則實現一個真正的隊列非常麻煩。只有在最新版本中,Oracle才支持SKIP LOCKED條款。 Find out more

+0

請參閱編輯我對我的問題 – 2009-09-28 18:31:00

+1

+1,這是我該怎麼做;良好的聯繫。 – DCookie 2009-09-29 00:38:36

0

如果你的意思是鎖定一張表,使其他會話無法從表中讀取,那麼不行。無論如何,你爲什麼要這麼做?

+0

看我的編輯。我可能會錯過一些明顯的... – 2009-09-28 17:55:34

2

TABLOCKXHOLDLOCK提示您提到似乎用於寫入,而不是讀取(基於http://www.tek-tips.com/faqs.cfm?fid=3141)。如果這就是你想要的,SELECT FOR UPDATE是否符合你的需求?

更新:根據您的更新,SELECT FOR UPDATE應該工作,假設所有客戶使用它。

更新2:您現在可能無法做任何事情,但這類問題實際上非常適合關係數據庫以外的其他應用,例如AMQP

+0

TABLOCKX將獨佔鎖定表(當另一個客戶端上有TABLOCKX鎖時,沒有其他客戶端可以鎖定該表)。這有效地防止其他客戶端讀取表(如果他們也請求鎖當然) – 2009-09-28 17:54:50

+0

一般來說,Oracle不鎖定讀取。 – 2009-09-28 18:55:11

4
1. Lock table 
    2. Read next item in queue 
    3. Remove item from the queue 
    4. Remove table lock 

在這種模式下,很多會話將只會等待鎖定,這似乎是一種浪費。高級隊列將是一個更好的解決方案。

如果你想要一個'自己動手'的解決方案,你可以看看SKIP LOCKED。它直到11g才被記錄,但是它存在於10g中。在這個算法中,你會做

1. SELECT item FROM queue WHERE ... FOR UPDATE SKIP LOCKED 
    2. Process item 
    3. Delete the item from the queue 
    4. COMMIT 

這將允許多個進程消耗隊列中的項目。

+0

我不認爲SKIP LOCKED子句可用於這種方式。選擇更新執行「正常」選擇和(概念上)比鎖定選定的行。使用SKIP LOCKED,您只需在嘗試鎖定選定行並鎖定您所能鎖定的行時不會掛起。沒有看到這可以如何幫助(2個會話發出「相同」的選擇結束,一個鎖定所有選定的行,第二個鎖定並返回0行) – 2009-09-29 06:04:26

+0

SKIP LOCKED如上所述工作。有2場會議。該查詢應該作爲遊標打開,然後獲取一行。每個會話都會得到一個不同的會話。 – 2016-06-29 19:00:19