在電信行業這種數據量巨大的環境中ora錯是一個很常見的錯誤這個錯誤使得應用失敗例如這一錯誤可能停止一個在深夜運行的批處理任務隨後也使依賴於該任務的其他任務失敗這使用戶不能及時得到所需的信息(如報表沒打印出來數據未被導出等等)盡管這一錯誤通常發生在大任務上但在小任務上也會發生
ORA通常是一個偶然出現的錯誤有時在發生了該錯誤以後重新運行該任務就有可能不再碰到類似的錯誤這個錯誤最麻煩的是它並不會立刻發生運行時間長的任務在錯誤失敗以前可能已經運行了一段時間了(可能幾個小時)只是簡單地重新運行該任務並不能保證它能成功可能在運行了一段時間以後仍然失敗
原因分析
ORA錯的根本原因是因為oracle要保證讀一致性讀一致性是指當有多個用戶對一個數據塊內的行進行修改時這些塊變髒或處於變化之中直到被確認在被確認以前它們對事務中的所有語句都是可見的但是對別的事務或語句而言是不可見的一旦確認以後對所有後繼的事務或語句就都是可見的了但在事務被確認前的語句不能看到修改因為這些修改還未發生
例如事務T (如對某大表的exp操作)在 開始而事務T (如對同一大表的update操作)在 時開始因為T 需遍歷一個很大的表其讀取要花很長的時間而T 可能對同一個表中的數據進行基於索引的更新操作這樣 T可能在幾秒鐘之內完成而T 可能要運行很長時間假定 分鐘當T 到達T 做過修改的地方時(根據當前的S C N時間戳可以識別出新作的改變)盡管T 所進行的寫已經被確認但為了保證讀一致性它不會讀到修改後的數據它只訪問在 時的數據在 時所做的改變不能被讀取 T 從回滾段中讀取改變前的數據以保證讀一致性但因為事務T已經提交T事務使用的回滾段oracle認為已經可以重新利用當回滾段太少或事務較密集時oracle有可能會用新事務覆蓋掉原來T事務的回滾段這時T事務讀到被T修改過的數據時再從回滾段中就無法找到修改前的數據這時就會報ORAsnapshot too old錯
下面我們可以結合實例來將此過程回溯一遍
()事務T在點開始執行了對某一個大表Test的exp操作(Test表數據量可能有幾千萬甚至更多)那麼按照經驗此操作可能需要執行分鐘左右或更長;
()事務T在點分開始執行對Test表某行的update操作並且操作條件上有索引(將col為的行col值由修改為)故此操作很快完成比如秒鐘完成操作並commit;
()此時事務T已經執行完畢而事務T還在執行中;
()當事務T需要將col為的行導出為dmp文件時Oracle為了保證讀一致性即T導出的必須是點時數據庫表的值故col為的行對於T任務來說值仍然為而非;
()由於T事務在點分前就已經做完(提交)並且T認為回滾段是可以重新利用的;
()如果此時由於回滾段太少或業務量較密集oracle就可能會重新利用剛才T事務所使用的回滾段這時T事務讀到此處時就會造成無法找到回滾段中修改前的數據產生錯誤
i中對回滾段管理
在i中可以有兩種解決方法來維護事務的讀一致性即或者使用自Oracle 以來就一直使用的回滾段或者是使用Undo Tablespace來進行的自動重做管理但是這兩種方法不能同時使用
建議在i 中使用回滾表空間而不是i 的回滾段模式來管理數據庫
()建立undotablespace
建立undotablespace的語法如下
create undotablespace tablespace_name
datafile fullpath+datafilename size XXM
[autoextend on|off next XX maxsize XX];
From:http://tw.wingwit.com/Article/program/Oracle/201311/17368.html