«код ошибки 5: база данных заблокирована» при использовании ContentProvider - PullRequest
6 голосов
/ 02 декабря 2011

У меня есть приложение, которое запускает действие со службой в отдельном процессе, который запускается и привязывается к действию.Служба содержит обработчик, который отправляет исполняемый файл для запуска после задержки.

Я хочу, чтобы каждый компонент регистрировался в базе данных, поэтому я реализовал поставщика контента, который имеет дело с доступом к базе данных, и я вызываю его из службыили действия через расширенные подклассы AsyncTask.

Все это прекрасно работает на эмуляторе, но когда я запускаю его в режиме отладки на своем телефоне, я получаю случайную ошибку блокировки базы данных при записи в базу данных:

ОБНОВЛЕНИЕ

Я внес некоторые изменения в обработку своей базы данных, и ошибка немного изменилась.

ERROR/Database(15235): Error inserting MY_MESSAGE
ERROR/Database(15235): android.database.sqlite.SQLiteException: error code 5: database is locked
ERROR/Database(15235):     at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
ERROR/Database(15235):     at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
ERROR/Database(15235):     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1591)
ERROR/Database(15235):     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1435)
ERROR/Database(15235):     at mypackagename.DatabaseHelper.insertLogging(DatabaseHelper.java:190)
ERROR/Database(15235):     at mypackagename.ContentProvider.insert(ContentProvider.java:139)
ERROR/Database(15235):     at android.content.ContentProvider$Transport.insert(ContentProvider.java:198)
ERROR/Database(15235):     at android.content.ContentResolver.insert(ContentResolver.java:604)
ERROR/Database(15235):     at mypackagename.Activity$LogToDatabase.doInBackground(Activity.java:642)
ERROR/Database(15235):     at mypackagename.Activity$LogToDatabase.doInBackground(Activity.java:1)
ERROR/Database(15235):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
ERROR/Database(15235):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
ERROR/Database(15235):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
ERROR/Database(15235):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
ERROR/Database(15235):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
ERROR/Database(15235):     at java.lang.Thread.run(Thread.java:1019)

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

Вопросы:

1) Почему я использую блокировки при использовании ContentProvider?
2) Почему это не отображается на эквивалентном эмуляторе API 2.3.3?
3) Означает ли тот факт, что ни один из моего кода не улавливает исключение, означает, что ошибка была обработана правильно, и я могу ее игнорировать?
4) Я читал в другом месте, кто-то предложил изменить время ожидания.Как бы я это сделал?

Ирония в том, что именно моя отладочная запись вызывает ошибку, не теряется на мне.

Если я не могу ее решить, мой следующий шаг - объединить сообщения регистрации в списке.и выгрузить их по десять штук за раз.

Вот путь к коду ошибки:

Активность:

private void logDatabaseMessage(String status, String message)
{
    String[] args = {status, message};
    LogToDatabase logTask = new LogToDatabase();
    logTask.execute(args);      
}

private class LogToDatabase extends AsyncTask<String, Integer, Void>
{
    @Override
    protected Void doInBackground(final String... args) 
    {
        try
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 
            String dateText = dateFormat.format(new Date());

            ContentValues loggingValues = new ContentValues();
            loggingValues.put(MyContentProvider.LOGGING_DATETIME, dateText);
            loggingValues.put(MyContentProvider.LOGGING_STATUS, args[0]);
            loggingValues.put(MyContentProvider.LOGGING_MESSAGE, args[1]);
            getContentResolver().insert(MyContentProvider.LOGGING_CONTENT_URI, loggingValues);
        }
        catch (Exception ex)
        {
            Log.e(TAG, "LogToDatabase.doInBackground threw exception: " + ex.getMessage());
            ex.printStackTrace();
        }               

        return null;
    }
}

ContentProvider:

@Override
public Uri insert(Uri uri, ContentValues values) 
{
    Uri _uri = null;
    long rowID = 0;

    try
    {
        switch (uriMatcher.match(uri))
        {
            case LOGGING:
                rowID = dbHelper.insertLogging(values);
                if (rowID == 0)
                    throw new SQLException("Failed to insert row into " + uri);

                _uri = ContentUris.withAppendedId(LOGGING_CONTENT_URI, rowID);
                break;

            default: throw new SQLException("Failed to insert row into " + uri);
        }

        if (rowID != 0)
            getContext().getContentResolver().notifyChange(_uri, null);    
    }
    catch (Exception ex)
    {
        Log.e(TAG, LogPrefix + "insert threw exception: " + ex.getMessage());
        ex.printStackTrace();
    }

    return _uri;    
}

DatabaseHelper:

public long insertLogging(ContentValues values)
{
    long rowID = 0;

    try
    {
        rowID = db.insert(LOGGING_TABLE, null,  values);
    }
    catch (Exception ex)
    {
        Log.e(TAG, LogPrefix + "ERROR: Failed to insert into logging table: " + ex.getMessage());
        ex.printStackTrace();
    }

    return rowID;
}

Ответы [ 2 ]

14 голосов
/ 02 декабря 2011

Возможно, вы обращаетесь к базе данных, используя несколько экземпляров SQLiteDatabase (или, возможно, SQLiteOpenHelper)?

У вас может быть только одно подключение к базе данных, в противном случае вы получите ошибки, с которыми вы столкнулись.1004 * Сама база данных SQLite является поточно-ориентированной , поэтому вы можете получить к ней доступ одновременно.

0 голосов
/ 23 января 2014

Также проверьте флаг многопроцессорности поставщика контента в манифесте.Каждый процесс будет иметь отдельное соединение с базой данных.

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