SQLiteDiskIOException в Android - PullRequest
       13

SQLiteDiskIOException в Android

10 голосов
/ 10 июля 2010

Мы получаем большое количество 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 записей. Более того, «объяснение плана запроса» в запросе указывает, что все объединения выполняются с индексированными столбцами. </p>

В каждом случае, который мы видели, пользователь запускал Android 2.1 на различных устройствах (DROID, Hero, EVO, возможно, на других). Примечательно, что мы не видели этого на паре устройств G1, которые у нас есть, даже когда они загружены другими приложениями.

Наконец, удаление и повторная установка оказались успешными в устранении проблемы, хотя, возможно, только временно.

Боюсь, что эта проблема является результатом повреждения данных в Android 2.1. У кого-нибудь есть возможные предложения, на что посмотреть? Может ли это быть связано с этой ошибкой Android в SQLiteDatabaseCorruptException

Руководство и решения очень ценятся.

Ответы [ 3 ]

7 голосов
/ 20 ноября 2010

Кажется, что у вас проблема с многопоточностью: один поток пытается получить данные, а другой или несколько пытается вставить некоторые данные в ваши таблицы, потому что исключение выдается из метода (getCount).

И не забудь;Курсор SQLite не является внутренне синхронизированным, поэтому, если вы используете этот курсор из нескольких потоков, вы должны выполнить свой собственный механизм синхронизации.

1 голос
/ 26 апреля 2012

У нас похожая проблема.При запуске нашего приложения возникает ошибка 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 голосов
/ 23 декабря 2014

одна причина, как сказал Бассель Х, многопоточный проблом, другая причина в том, что БД недоступна, т.е. БД удалена или sdcard недоступен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...