2010-07-10 10 views
10

Jesteśmy coraz dużej liczby SQLiteDiskIOException błędów w naszej aplikacji Android, stos ślady podobne do następujących:SQLiteDiskIOException w Androidzie

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) 

Ten niedawno począwszy dzieje się kilka tygodni temu, ale żadne znaczące zmiany w bazie danych trwało miejsce w dokładnym wydaniu, w którym rozpoczęło się zgłaszanie tego problemu. Pomimo posiadania (moim zdaniem) odpowiednich indeksów, ten wyjątek został zgłoszony bardziej niż jesteśmy zadowoleni z wywołań cursor.moveToFirst() po zakończeniu zapytania, co widać na podstawie śledzenia stosu. Do tej pory nie byliśmy w stanie się rozmnażać.

Zapytanie jest nieco skomplikowane, z trzema lewymi złączeniami. Poniżej znajduje się reprezentatywne zapytanie, a niektóre kolumny identyfikacyjne zostały zmienione w celu ochrony niewinnych.

Inne źródła sugerują, że próbujemy wyciągnąć zbyt dużo danych, ale tak się nie dzieje. Trzy przypadki użytkowników, w których udało nam się uzyskać pełne liczby wierszy bazy danych, pokazują: cse z < 2000 wpisów, emed z < 150 wpisów i pre z 0 lub 7 wpisami. Ponadto "wyjaśnij plan zapytania" w zapytaniu oznacza, że ​​wszystkie połączenia są wykonywane względem indeksowanych kolumn.

W każdym przypadku, w którym to widzieliśmy, użytkownik korzystał z systemu Android 2.1 na różnych urządzeniach (DROID, Hero, EVO, ewentualnie innych). Warto zauważyć, że nie widzieliśmy tego na kilku urządzeniach G1, jakie mamy, nawet gdy są one obciążone innymi aplikacjami.

Wreszcie, odinstalowanie i ponowne zainstalowanie okazało się skuteczne w usunięciu problemu, choć możliwe, że tylko tymczasowo.

Obawiam się, że ten problem jest wynikiem uszkodzenia danych w systemie Android 2.1. Czy ktoś ma możliwe sugestie, na co zwrócić uwagę? Może to być powiązane z

Wskazówki i rozwiązania są bardzo cenne.

+0

Czy możesz zrobić małą aplikację, która odtwarza problem? Jeśli tak, prześlemy go na http://code.google.com/p/android/issues/list – Macarse

+0

Od jakiegoś czasu próbuję odtworzyć ten problem za pośrednictwem naszej aplikacji. Nie próbowałem małego programu, szczególnie w wersji 2.1. To może być kolejna ścieżka, jeśli najnowsze zmiany nie rozwiązują problemu. Dzięki. –

+0

Wyobrażam sobie, że ludzie kupowali nieczyste karty SD, które cierpią z powodu korupcji. –

Odpowiedz

7

Wygląda na to, że masz problem z wieloma wątkami, jeden wątek próbuje uzyskać dane, podczas gdy inny lub więcej próbuje wstawić niektóre dane do tabel, ponieważ wyjątek jest generowany z metody (getCount).

Nie zapomnij; Kursor SQLite nie jest wewnętrznie zsynchronizowany, więc jeśli używasz tego kursora z wielu wątków, powinieneś wykonać swój własny mechanizm synchronizacji.

+2

Czy ktoś może potwierdzić tę odpowiedź? Ponieważ mam poważne problemy z przekonaniem, że tak właśnie jest? Czy ktoś był w stanie stworzyć test, za który w istocie polegają kursory? –

1

Mamy podobny problem. Kiedy pojawia się nasza aplikacja, pojawia się błąd souch. W przypadku metody onCreate sprawdzamy czy istnieje jakaś baza danych w ścieżce aplikacji. Jeśli wystąpi jakakolwiek baza danych, wywołujemy taki kod:

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; 
    } 

Jeśli nie ma bazy danych (pierwsze uruchomienie aplikacji), kopiujemy ją z zasobów. Ale czasami pojawia się SQLiteDiskIOException i wywołania bazy danych z zasobów.

0

Jednym z powodów jest Bassel Kh stwierdził, multi wątek problom, inny jest db jest niedostępny, czyli. db jest usuwany lub sdcard jest niedostępny.