SQLCipher выбрасывает исключение во вставке

Я получил исключение в моем коде.

10-10 22:05:33.866  5725  5725 E AndroidRuntime: Caused by: net.sqlcipher.database.SQLiteDiskIOException: error code 10: disk I/O error
10-10 22:05:33.866  5725  5725 E AndroidRuntime:    at net.sqlcipher.database.SQLiteStatement.native_execute(Native Method)
10-10 22:05:33.866  5725  5725 E AndroidRuntime:    at net.sqlcipher.database.SQLiteStatement.execute(SQLiteStatement.java:58)
10-10 22:05:33.866  5725  5725 E AndroidRuntime:    at net.sqlcipher.database.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:2074)

Это происходило только один раз (пока) среди тысяч успешных вставок и выборок, поэтому я подозреваю, что существует какое-то состояние гонки между различными потоками в одном и том же процессе, пытающемся получить доступ к одной и той же базе данных.

Фактический код не важен, это просто вставка новой записи, а параметр on конфликта говорит, что игнорирует любой конфликт:

    ContentValues values = new ContentValues();
    // values.put(); calls go here, nothing strange about the data
    db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);

Архитектурно, в моем Сервисе есть одноэлементный объект, инкапсулирующий одно непрерывно открытое соединение с базой данных, а перед ним - кеш. Несколько потоков вызывают объект из разных мест в Сервисе для вставки данных, обычно это слушатели, которые регистрируют такие вещи, как положение GPS, состояние батареи и т. Д. Чтение обычно происходит из кэша и не попадает в базу данных.

Сначала я подумал, что, возможно, мне нужно синхронизировать класс, через который осуществляется поток доступа к базе данных (пахнет так, будто два разных потока могут пытаться вставить практически в одно и то же время, что на практике случается редко), но этот ответ кажется говоря, что я должен быть в состоянии сделать это без проблем. "Вставки, обновления, удаления и считывания обычно выполняются из нескольких потоков". Следует отметить, что исключение говорит "ошибка ввода-вывода", а не "база данных заблокирована".

Обновление: я добавил следы logcat и исключение при каждом доступе к базе данных. После этого я получил еще два исключения. В обоих случаях осуществлялся только один доступ к базе данных. Оба были простыми вставками. Первый бросил исключение через 1,2 секунды после начала вставки, что кажется невероятно высоким. Второе заняло только 38 мс, что выглядит примерно на среднем уровне.

Проблемы не хватает памяти: у меня есть 27 ГБ бесплатно. Мне трудно поверить, что это проблема и со вспышкой, так как я не вижу никаких других ошибок при записи в нее. Я также не видел подобных проблем со старым приложением, которое использует ту же библиотеку SQLCipher, но закрывает базу данных после каждой вставки.

Обновление 2: в обработчик исключений я добавил код, чтобы немедленно повторить попытку вставки, и до сих пор я не получил второе исключение на данный момент:

    try {
        ret = db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);
    } catch (Exception e) {
        Log.d(logtag,"exception:"+e);
        try {
            ret = db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);
        } catch (Exception e1) {
            Log.d(logtag,"exception2:"+e1);
        }
        return 0;
    }

0 ответов

Другие вопросы по тегам