2010-07-10 53 views
10

我們已經看到了大量SQLiteDiskIOException錯誤在我們的Android應用程序,與堆棧跟蹤類似以下內容:SQLiteDiskIOException Android中

E/AndroidRuntime(2252): Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error 
E/AndroidRuntime(2252): at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method) 
E/AndroidRuntime(2252): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:75) 
E/AndroidRuntime(2252): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:288) 
E/AndroidRuntime(2252): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:269) 
E/AndroidRuntime(2252): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:171) 
E/AndroidRuntime(2252): at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:248) 
E/AndroidRuntime(2252): at com.company.android.CActivity$QueryTask.doInBackground(CActivity.java:1660) 

這家新近開始發生在幾個星期前,但沒有顯著數據庫更改了發佈此問題報告的確切發佈。儘管擁有(我相信)適當的索引,但是在查詢完成後,這種例外情況已被報告超過我們對cursor.moveToFirst()調用的滿意度,這一點您可以從堆棧跟蹤中看到。到目前爲止,我們已經完全無法重現。

該查詢有點複雜,有三個左連接。下面是一個有代表性的查詢,爲了保護無辜者,更改了一些標識列。

select distinct c._id as _id,c.type as type,c.name as name,c.slug as slug,c.description as description,c.extra1 as extra1,c.extra2 as extra2,c.extra3 as extra3,c.extra4 as extra4,c.extra5,c.extra6 as extra6,c.extra7 as extra7,c.extra8 as extra8, c.extra9 as extra9,c.sslug as sslug, 
    c2.name as sname, 
    p.type as prel, 
    em.dS as dS,em.eS as eS 
from cse as c 
left join cse as c2 on c.sslug=c2.slug 
left join emed as em on c.slug=em.slug 
left join pre as p on c.sslug=p.slug 
where c.pslug='slug' AND c.user='user' AND c.csource='csource' 
order by c.type asc, c.extra6 desc, c.sortorder asc 

其他來源建議我們試圖提取太多的數據,但事實並非如此。我們能夠獲得完整數據庫行數的三個用戶案例顯示: cse含有< 2000條目, 含有< 150條目,而 含有0或7個條目。 此外,在查詢中解釋查詢計劃表明所有連接都是針對索引列完成的。

在每種情況下,我們都看到了這種情況,用戶在各種設備(DROID,Hero,EVO,可能還有其他設備)上運行Android 2.1。值得注意的是,我們還沒有在我們的G1設備上看到過這一點,即使它們裝載了其他應用程序。

最後,卸載和重新安裝已成功清除問題,但可能只是暫時性的。

我擔心這個問題是Android 2.1中數據損壞的結果。 有沒有人有可能的建議,看看什麼? 這可能與this Android bug on SQLiteDatabaseCorruptException

指導和解決方案非常感謝。

+0

你可以製作一個重現此問題的小應用程序嗎? 如果是這樣,我會將其上傳到http://code.google。com/p/android/issues/list – Macarse 2010-07-11 01:51:10

+0

我一直試圖通過我們的應用程序重現一段時間的問題。我還沒有嘗試過一個小程序,特別是2.1。如果最新的更改無法解決問題,那麼這可能是下一個路徑。謝謝。 – 2010-07-11 23:15:45

+0

我想象一下,人們買了骯髒的SD卡,遭受腐敗。 – 2010-11-08 18:13:18

回答

7

看來你有多線程問題,一個線程試圖獲取數據,而另一個或多個嘗試向表中插入一些數據,因爲異常是從方法(getCount)拋出的。

也別忘了; SQLite遊標不在內部同步,所以如果你從多個線程使用這個遊標,你應該執行你自己的同步機制。

+2

任何人都可以確認這個答案嗎?因爲我有一些嚴重的問題認爲這是事實?有沒有人能夠創建一個測試用例,這裏的遊標確實存在錯誤? – 2013-09-03 23:49:20

1

我們有類似的問題。當我們的應用程序啓動時發生souch錯誤。 在onCreate方法中,我們檢查應用程序路徑中是否有任何數據庫。如果發生任何數據庫,我們調用這樣的代碼

public boolean createDataBase() throws IOException 
    { 
     boolean dbExist = checkDataBase(); 

     if(dbExist) 
     { 
      //do nothing - database already exist 
     } 
     else 
     { 
      //By calling this method and empty database will be created into the default system path 
      //of your application so we are gonna be able to overwrite that database with our database. 
      this.getReadableDatabase(); 
     } 

     return dbExist; 
    } 



    private boolean checkDataBase() 
    { 
     SQLiteDatabase checkDB = null; 

     try 
     { 
      String myPath = DATABASE_PATH + DATABASE_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

     } 
     catch(SQLiteException e) 
     { 

     } 

     if(checkDB != null) 
     { 
      checkDB.close(); 
     } 

     return checkDB != null ? true : false; 
    } 

如果沒有數據庫(應用程序第一次運行),我們從資源複製它。 但有時會發生SQLiteDiskIOException和數據庫調用資源。

0

一個原因是Bassel Kh說,多線程問題,另一個是db不可用,即。數據庫被刪除或SD卡是不可靠的。