2013-04-02 43 views
1

我一直在尋找一段時間,找不到這個。我與甲骨文合作,有一個類似,對於循環:自動提交開啓時顯式提交是否正常?

BEGIN 
    FOR YEARIDs IN (SELECT DISTINCT YEARID From MyTable) 
    LOOP 
    UPDATE (
       SELECT ...... 
      ) 
    SET  MyFlag = 1; 
    COMMIT; -- Added 
    END LOOP; 
END; 

自動提交被打開,但現在看來,提交不會發生,直到整個for循環結束。因此,我在上面的代碼中添加了Commit語句。這是否會導致任何意想不到的結果,還是這違反了最佳做法? (即我不應該進行顯式調用時自動提交開啓以犯?)

感謝, 斯科特

編輯:哎呀...我使用的是Oracle 11g和Oracle SQL Developer中的客戶端。

編輯:謝謝你的迴應,迄今。在查詢運行的時間點,數據正在生成&調整。沒有其他連接應該嘗試訪問數據。至於爲什麼我經常提交,在開發過程中,我針對數據的一個子集運行查詢,查詢運行得很好。該表擁有大約1400萬條記錄,我正在測試大約10萬條記錄。查詢相當複雜,並且在大約5分鐘內針對這個子集運行。當我對整個表格運行時,查詢運行時間超過14小時,無法更新任何記錄。我的理論是,持有這麼多撤銷信息可能會消耗開發服務器上的所有可用資源。如果我頻繁提交,撤消信息可以被釋放並重新使用。是的,這很慢。但是,如果查詢將實際完成,即使需要一整夜,也可以將其移至測試服務器。 (性能調整可以在以後完成。)截止日期早已過去。 (在錯過最後期限之後,我被帶進來提供幫助,而我的專業領域不在Oracle中。)

+0

不應該犯是外循環? (在END LOOP之後)。 – Fergus

+2

自動提交將在聲明完成後發生,在這種情況下,整個匿名塊完成;不是在'for'循環之後。學術在這種情況下,因爲無論如何都要注意循環,但仍然......爲什麼你要這麼頻繁地提交? –

+1

閱讀這篇關於Oracle autocommit(或缺乏)細微差別的文章。 http://asktom.oracle.com/pls/apex/f?p=100:11:0::NO::P11_QUESTION_ID:314816776423。正如其他人所指出的那樣,在每次迭代之後提交是一個壞主意,但如果您有一個覆蓋這些問題的用例,請在您的問題中分享。 –

回答

7

在循環內部提交通常是一個壞主意(因此允許任何工具自動提交)。

在循環內部提交使編寫可重啓代碼更加困難。如果在3次迭代後遇到錯誤會發生什麼?您現在已成功提交了2 UPDATE報表的結果。據推測,您需要確定哪些行已更新,並編寫代碼來反轉更新,或者您必須添加代碼,以避免嘗試更新這兩個成功值的數據。這當然是可能的。但是它涉及編寫一堆代碼來跟蹤你的進度,並且通常會讓你的代碼更加複雜。

在循環內部提交會使代碼變慢。承諾通常是一個相當昂貴的操作。因此,在循環中做它通常是一個壞主意。如果你只有幾十次循環迭代,那麼它就不是什麼問題。但是,如果您有數百次或數千次迭代,您可以輕鬆完成絕大部分時間。

在循環內部提交會大大增加導致ORA-01555錯誤的風險。您對MyTable的查詢需要讀取一致的數據視圖。但是,如果您在循環中提交,那麼您告訴Oracle您的會話不再需要較舊的UNDO數據。如果Oracle恰好清除了循環的後續迭代所需的數據,則會發生錯誤。然後,您又回到了處理不可重新啓動的代碼,您經歷了N次迭代,但您不知道哪些年份已處理或需要處理哪些年份。

在循環內部提交可能會產生數據一致性問題。例如,如果某個其他會話正在運行報告,那麼這些報告很容易看到部分更新的數據,這通常意味着數據不一致。如果3年的數據發生了變化,但其他年份的數據並沒有發生變化,那麼可以很難理解報告,人們(或流程)很容易做出錯誤的決定。

在循環內部提交也會使您的代碼重複使用的次數減少。如果您的代碼包含提交(或回滾,而不是您在塊內部建立的保存點),則不能由任何其他不想要其事務提交的代碼調用。這會導致人們嘗試在沒有事務控制的情況下重新實現自己的邏輯,或者錯誤地違反事務完整性,這不可避免地導致他們構建引入數據一致性問題的應用程序。

+0

刪除撤消信息實際上是我考慮這種方法的原因。 (請參閱原文中的第二次編輯。)我知道這不是好的形式。但我越來越絕望了。針對整個數據集的每次測試都失敗了,需要花費很多時間才能運行。我當然願意接受其他建議。 (並感謝您的迴應。) – DeadZone

+0

@DeadZone - 迴應Alex Poole的上述評論,如果您用完'UNDO',Oracle會告訴您。除了磁盤空間之外,保留舊的'UNDO'並不需要任何費用。所以這似乎不是一個好方法。它當然不會提高性能。如果您遇到性能問題,您可能希望創建一個新問題,讓您向我們展示查詢和查詢計劃以及您擁有的任何其他信息(例如等待事件)。 –

0

DBMS_PARALLEL_EXECUTE是一個奇妙的功能之一,我們一直在使用mn行沒有任何中斷的大表。

這確保了高可用性,可重啓性並利用並行處理。

看到這個 https://oracle-base.com/articles/11g/dbms_parallel_execute_11gR2

我認爲沒有錯以規則的間隔之後提交的數據(比如1000 - 10000行,這取決於行的大小)爲好。事實上,對於大數據遷移/回掃,建議大塊並承諾避免'ORA-01555快照過早'。

這也可以防止在基表上更長時間的鎖定。

正如評論別人,「自動提交」不需要在這裏...