OAF: 關於"鈍化" Passivation

這篇是前段時間那個bug 的續篇. 那個bug 從兩年前 Pan 就在搞, 後來老大也在搞, 知道今天才弄明白是什麼原因導致的. 我跟這個 bug 整整兩個月, 在 ATG 的幫助下, 總算知道了原因.

Passivation, 翻譯作”鈍化”, 聽名字也不知道是幹什麼的. 開發文檔Chapter 6, OA Framework State Persistence Model (Passivation) 裏面有詳細介紹.
簡單來說, 鈍化就是在資源消耗非常高時, 應用會把空閒的線程的狀態保存到數據庫中, 把這些資源給其他用戶使用. 當空閒的線程被喚醒時, 保存的狀態會被恢復回來. 如果出現 timeout 的情況, 可以用來恢復用戶未完成的事務.
但是鈍化是有風險的. 如果沒有啓用鈍化, 在一個事務中的多個多個頁面中操作, AM 和 DBtxn 都被完全保留下來, 這樣以來跟很多數據庫連接狀態相關的功能都可以用, 比如 PL/SQL EO 可以不用 insertRow() deleteRow() 來插入刪除數據.
在開發文檔中, PL/SQL Entity Object Design and Development 這一章, 裏面說了這麼一句”You should call your PL/SQL insert procedure in your insertRow() method”, 是說如果要用 PL/SQL 代碼插入數據的話, 那麼就要在 insertRow() 裏面去調用, 而不是直接調用. 開始我不明白爲什麼. 文檔中緊接着一條warning: “Do not bypass the insert PL/SQL call within your insertRow() method since BC4J doesn’t have any way to know that you didn’t actually perform the insert, and might try to lock the row at some point since it expects it to exist.” 我們這個bug 報的錯就是這條 warning 所導致的. 在我們的代碼中, 直接調用 PL/SQL 代碼插入了表, 繞過了 insertRow(), 導致BC4J 不知道我們插入了數據. 而當OAF 代碼用 select for update nowait 嘗試鎖這條記錄的時候, 就報了找不到記錄的錯. 現在看起來, 原因就是如果啓用了鈍化, BC4J 又不知道我們插入了數據, 於是鈍化的時候把數據庫連接session 就丟掉了. 而如果用insertRow() 的話, 插入的數據信息會被AM 保存下來. 鈍化的時候AM 中就帶有了這個插入信息, 所以之後就不會報錯. 根據我的測試, 如果不啓用鈍化, 那麼數據庫session 就一直不會丟, 自然不會報錯. 如果用insertRow(), 同時啓用鈍化, 數據庫session 會丟掉, 但是依然不會報錯.
啓用鈍化就是在建立 AM 的時候設置一條屬性, RETENTION_LEVEL=MANAGE_STATE. 還需要設置一些其他的profile 之類的東西, 但是不重要了, 因爲我覺得還是不要啓用鈍化的好. 因爲性能方面未必會好很多, 畢竟把狀態寫入數據庫, 再從數據庫讀取出來也是要消耗資源的. 況且這可能會帶來這種詭異的bug, 太蛋疼了. 而且在開發文檔裏面, 這一章的開頭也說, “Information about the forthcoming passivation feature is provided for preview/planning purposes only; passivation is not supported in Release R12.” 還是不用的好.
root AM 和 DBtxn 是很重要的東西, 在寫代碼的時候最好能顯式釋放和刷新. 不僅代碼閱讀性好一些, 而且能避免一些框架層面的bug, 而這些bug 要跟蹤確實會消耗很大的精力.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章