2012年11月11日 星期日

曾遇到的DB問題 (一)


三個跟DB相關的問題,兩個是我還在android時遇到的;一個則是在我開始寫VB6以後看到的。

()
當時是有一個ANR(Application Not Responding)issue,後來根據log發現是因為發生DB lock,結果造成等待DB等到發生了ANR。那為什麼會發生DB lock呢?我記得當時我跟一位同事看code看了很久,看起來好像都沒有問題,直到一直查到源頭,另一個同事寫的存取DBlibrary,終於讓我們發現了一個問題。原本library的設計概念是把存取DB的類別使用singleton模式來實作,但是卻沒有將建構子的存取權限設為private,使得在開發Provider時誤用new來實體化DBHelper


所以當多執行緒操作DB時,就可能發生new兩次實體的狀況。也就是說當A物件先使用DBHelper,然後B物件又使用DBHelper,接著就會發生DB lock。使得B物件無法使用DBHelper,於是他只好等待到天荒地老到發生ANR。發現了這個root cause後,我們便將建構子的存取權限設為private,並把要使用到DBHelper物件的程式碼,改為以getInstance來獲取實體,這個issue也就這樣解了。


()
第二個也是DB的問題,這個問題是在第一次使用該AP時才會發生的issue,而且還必須依照某一特定的步驟才會發生。問題是這樣的,有一個應用程式A,還有一個應用程式A的外掛程式B。當使用者還沒第一次執行過A之前,先使用了B就會發生B無法外掛到A的問題。這個問題很特殊,而且可能跟上面DB lock問題一起發生。我試了很久才終於找到這個issue的重覆產生步驟,因為它只會發生在A從來沒有執行過的情況下,而這個情況通常只會發生在剛刷完新ROM的機子中。

主要的原因是這樣的:
1. 在第一次執行A之前,A所需要用到的資料庫是完全不存在的(我想這應該只會發生在Android)
2. 目前實作的機制是將可以外掛到A的來源資料儲存在DB中。因此,資料庫在創建時必須自動加入A可以接受外掛的來源,否則外掛程式皆無法外掛到A之中。

A從沒被執行過,DB還沒產生出來時。在執行B的時候,B會透過一些機制來使用AProvider,接著A會發現沒有DB存在,然後開始create一個DB。當DB建好後,再透過一些機制將外掛來源寫進DB中。也就是說,這是一個兩步驟的動作,所以當A只做到第一個動作時,B便開始想外掛進A,然後就會出現A發現DB中並沒有B可作為外掛來源的資料,於是拒絕B的外掛,並造成B外掛失敗。這個問題簡單來說,其實是因為多執行緒的時間差造成的問題。最後的解法是,當A確定DB建好且外掛來源也已經寫進資料庫中時,再發送一個訊息給B,讓B再做一次外掛即可解決。

沒有留言:

張貼留言