2013-04-08 73 views
1

我有一個工作正在運行,隨機地隨着ORA 54錯誤而異常終止。當我檢查代碼時,我可以看到NOWAIT的存在導致了這個問題。現在我決定測試它,並寫下如下匿名塊。ORA 54資源忙碌錯誤

declare 
    cursor c1 is 
     select * from table where column_1=2 and column_2=2 and column_3=6 
     for update of column_4 nowait; 
    record_locked exception; 
    pragma exception_init (record_locked, -54); 
begin 
    begin 
     open c1; 
    exception 
     when record_locked then 
      dbms_output.put_line('Faced a locked record. Waiting for 2 minutes..'); 
      dbms_lock.sleep(120); 
      open c1; 
    end; 
exception 
    when others then 
     dbms_output.put_line('Exception Occured '||SQLCODE||SQLERRM); 
end; 

我開了一個會議,並跑到下面的查詢

select * from table 
where column_1=2 and column_2=2 and column_3=6 
for update of column_4 nowait; 

我沒有提交或回滾,並保持該會話開放。現在我在另一個會話中運行上面的匿名塊。等待2分鐘後,它發生ORA 54錯誤。所以我相信我的假設是正確的。

現在的情況是,當我以相同的方式在測試環境中運行包含第一個匿名塊的整個作業代碼時,它無需等待就等待鎖定的記錄。當我通過回滾釋放鎖時,它更新了記錄併成功完成。

我想知道爲什麼?

+0

奇怪。但是我有一個問題:當你選擇... for update wait 120'時,你爲什麼要編寫自己的等待期,而不需要額外的代碼呢? – 2013-04-08 08:54:03

+0

Colin:我想在日誌中顯示工作面臨一個鎖定的記錄,然後等待2分鐘,然後abending ....但即使是原始代碼workng不同的方式在生產和測試.. :( – prabhath 2013-04-08 09:36:02

回答

1

由於您的表格內容不同,您會從測試和生產中獲得不同的結果。您的測試表不包含任何與where子句匹配的行,因此您的會話不會彼此阻塞。

嘗試向符合條件的測試表中添加至少一行,並且您應該獲得與生產中相同的結果。

+0

嗨Frank:謝謝你的答覆,實際上在我的測試表中,我創建了20條記錄,它們與where子句匹配,哪些在生產中是相同的。還有一點疑問。會話是否應該互相阻塞,以便拋出異常或特定會話現在已經被阻塞了,只要ORA 54錯誤就足夠了 – prabhath 2013-04-10 07:09:57

+0

@prabhath我真的不明白你的評論的第二部分 - 你是問ORA-00054是否會在你的場景中出現?在我看來,是的。另外,你真的100%確定測試和生產環境是完全一樣嗎?(事務隔離級別等) – 2013-04-10 07:21:33

+0

我不確定事務隔離級別。我的疑問就是爲什麼sa我在2個不同的環境中運行的代碼有不同的行爲。包含NOWAIT的代碼在生產中拋出異常。但是當我鎖定幾條滿足測試環境中條件並運行作業的記錄時,不會拋出錯誤等待,直到我釋放鎖並更新記錄。我確認了相同的使用日誌,沒有記錄更新以及記錄的最後更新用戶。 – prabhath 2013-04-10 08:47:06