我有兩個步驟Spring Batch的:替代JpaPagingItemReader導致ORA-01555
- 步驟1批作業:轉到外部數據庫,調用存儲過程,編寫JPA實體並持續到內部數據庫的標誌NOT_PROCESSED。
- 第2步:遍歷剛纔保存的實體標誌NOT_PROCESSED,對它們進行處理,並寫更新實體回(不更新標誌)
一旦所有的人都被處理的標誌個個已更新爲已處理。即全部或全部更新。
第1步是好的,工作很順利。
第2步基本上是JpaPagingItemReader,其中pageSize = 4,處理器集合(主要是http調用)和JpaItemWriter,其中commit-interval = 1。 (我知道建議使pageSize等於commit-interval,這正是我所擁有的)。它也是一個多線程的步驟,包含10個線程完成這項工作。
這在第2步說,我有兩個類型的查詢:
閱讀:
select * from ENTITY where processed=false order by id
嵌套到兩個查詢分頁select ... from (select .. where rownum < M) where rownum >= N
寫:
update ENTITY set .. where id = ID
對於某些原因,當我有足夠的實體我臭名昭着:
ORA-01555,快照太舊:回滾段名稱爲「」 太小
我不知道確切的錯誤的(撤消統計並沒有顯示什麼不好的原因,所以希望數據庫管理員將很快找到罪魁禍首),但同時我認爲讀取查詢的功能非常糟糕。這樣的分頁查詢對於數據庫來說很難,但是我猜你讀的時候,同時更新你讀的條目可能會導致這種錯誤。
我想改變步驟2中採取的方法,而不是閱讀頁面。我想將所有ID都讀入內存只有一次(即給我所有我需要處理的實體的ID),然後給每個線程從該列表中的ID。鏈中的第一個處理器將通過JPA通過id獲取實體。這樣我就可以逐一更新和寫入實體,同時我只需要閱讀一次我只需要的ID。
我的問題是我找不到這種閱讀器的開箱即用解決方案。有什麼我可以使用的嗎?
爲什麼不執行select + update作爲單個SQL語句?另外什麼是你的隔離級別? – ibre5041
由於要獲取更新值,如果我簡化了一個非常複雜的邏輯,則更新取決於外部服務調用。 oracle默認,afair讀取提交。 –
你可以得到這個錯誤的原因主要有兩個,第一是修改lob時,第二是你的查詢執行花費太多時間。 「太多」通常定義爲視圖v $ undostat中的列TUNED_UNDORETENTION。這將顯示什麼是合理的撤銷數據庫保留,特別是UNDO tbs大小,以及特定的事務活動。 – ibre5041