"错误code 5:数据库已锁定"使用ContentProvider的时 [英] "error code 5: database is locked" when using a ContentProvider

查看:145
本文介绍了"错误code 5:数据库已锁定"使用ContentProvider的时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行与该启动并结合到活性的单独的处理的服务的活动的应用程序。该服务包含投递一个可运行的处理程序,以延迟后运行。

我想每个组件登录到数据库,让我实现了数据库访问涉及内容提供商和我通过扩展的AsyncTask子类调用它从服务或活动。

这一切精美的作品在模拟器上,但是当我在调试我的手机上运行它,我得到我的数据库写零星的数据库锁定错误:

更新

我做了一些改变,我的数据库处理和错误略有改变。

  ERROR /数据库(15235):错误插入MY_MESSAGE
ERROR /数据库(15235):android.database.sqlite.SQLiteException:错误code 5:数据库已锁定
ERROR /数据库(15235):在android.database.sqlite.SQLiteStatement.native_execute(本机方法)
ERROR /数据库(15235):在android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
ERROR /数据库(15235):在android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1591)
ERROR /数据库(15235):在android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1435)
ERROR /数据库(15235):在mypackagename.DatabaseHelper.insertLogging(DatabaseHelper.java:190)
ERROR /数据库(15235):在mypackagename.ContentProvider.insert(ContentProvider.java:139)
ERROR /数据库(15235):在android.content.ContentProvider $ Transport.insert(ContentProvider.java:198)
ERROR /数据库(15235):在android.content.ContentResolver.insert(ContentResolver.java:604)
ERROR /数据库(15235):在mypackagename.Activity $ LogToDatabase.doInBackground(Activity.java:642)
ERROR /数据库(15235):在mypackagename.Activity $ LogToDatabase.doInBackground(Activity.java:1)
ERROR /数据库(15235):在android.os.AsyncTask $ 2.call(AsyncTask.java:185)
ERROR /数据库(15235):在java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:306)
ERROR /数据库(15235):在java.util.concurrent.FutureTask.run(FutureTask.java:138)
ERROR /数据库(15235):在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
ERROR /数据库(15235):在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:581)
ERROR /数据库(15235):在java.lang.Thread.run(Thread.java:1019)

我没有把太多的细节之前,因为我认为这是不同的进程或线程的问题,但现在我想这个问题更可能位于code调用数据库。

问题:

1)为什么我打的锁,当我使用ContentProvider的?结果
2)为什么这个不上的等效API 2.3.3模拟器现身?结果
3)不执行,没有我的code的捕获异常意味着该错误已妥善处理,我可以忽略这个事实?结果
4)我在另一个地方有人建议调整忙超时读取。我会怎么做呢?

这是这是造成该错误不输于我。我的调试日志具有讽刺意味的​​

如果我解决不了,我的下一个步骤是捆绑日志消息了一个列表,并倾倒出来十批一次。

这里的路径通过code到错误:

活动:

 私人无效logDatabaseMessage(字符串状态,字符串消息)
{
    字串[] args = {状态,消息};
    LogToDatabase logTask =新LogToDatabase();
    logTask.execute(参数);
}私有类LogToDatabase扩展的AsyncTask<字符串,整数,太虚>
{
    @覆盖
    保护无效doInBackground(最终字符串参数... args)
    {
        尝试
        {
            SimpleDateFormat的日期格式=新的SimpleDateFormat(YYYY-MM-dd'T'HH:MM:SS.SSS);
            字符串dateText = dateFormat.format(新的Date());            ContentValues​​ loggingValues​​ =新ContentValues​​();
            loggingValues​​.put(MyContentProvider.LOGGING_DATETIME,dateText);
            loggingValues​​.put(MyContentProvider.LOGGING_STATUS,ARGS [0]);
            loggingValues​​.put(MyContentProvider.LOGGING_MESSAGE,ARGS [1]);
            。getContentResolver()插入(MyContentProvider.LOGGING_CONTENT_URI,loggingValues​​);
        }
        赶上(异常前)
        {
            Log.e(TAGLogToDatabase.doInBackground抛出异常:+ ex.getMessage());
            ex.printStackTrace();
        }        返回null;
    }
}

的ContentProvider:

  @覆盖
公共乌里插入(URI URI,ContentValues​​值)
{
    乌里_uri = NULL;
    长ROWID = 0;    尝试
    {
        开关(uriMatcher.match(URI))
        {
            案例记录:
                ROWID = dbHelper.insertLogging(值);
                如果(ROWID == 0)
                    抛出新的SQLException(无法插入行+ URI);                _uri = ContentUris.withAppendedId(LOGGING_CONTENT_URI,ROWID);
                打破;            默认:抛出新的SQLException(无法插入行+ URI);
        }        如果(ROWID!= 0)
            。的getContext()getContentResolver()有NotifyChange(_uri,NULL);
    }
    赶上(异常前)
    {
        Log.e(TAG,登录preFIX +插入抛出异常:+ ex.getMessage());
        ex.printStackTrace();
    }    返回_uri;
}

DatabaseHelper:

 众长insertLogging(ContentValues​​值)
{
    长ROWID = 0;    尝试
    {
        ROWID = db.insert(LOGGING_TABLE,空,价值);
    }
    赶上(异常前)
    {
        Log.e(TAG,登录preFIX +错误:无法插入到记录表:+ ex.getMessage());
        ex.printStackTrace();
    }    返回ROWID;
}


解决方案

您可能访问使用多个SQLiteDatabase(或者SQLiteOpenHelper)实例数据库?你只能有一个连接到数据库,否则你会得到您所遇到的错误。 SQLiteDatabase本身是线程安全的,这样你就可以同时访问它。

I have an application that runs an activity with a service in a separate process that is started and bound to the activity. The service contains a handler that posts a runnable to be run after a delay.

I want each component to log to the database, so I implemented a content provider that deals with database access and I call it from the service or activity via extended AsyncTask sub-classes.

This all works beautifully on the emulator, but when I run it in debug on my phone I get a sporadic database locked error on my database writing:

UPDATE

I made some changes to my database handling and the error has changed slightly.

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)

I didn't put much detail before in because I thought it was an issue with different processes or threads, but now I'm thinking the problem is more likely located in the code calling the database.

Questions:

1) Why am I hitting locks when I'm using a ContentProvider?
2) Why does this not show up on an equivalent API 2.3.3 emulator?
3) Does the fact that none of my code catches an exception mean that the error was handled properly and I can ignore it?
4) I read in another place someone suggesting adjusting the busy timeout. How would I do that?

The irony that it's my debug logging that's causing the error is not lost on me.

If I can't solve it, my next step is to bundle the logging messages up in a list and dump them out in batches of ten at a time.

Here's the path the through the code to the error:

Activity:

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

解决方案

Are you possibly accessing the database using multiple SQLiteDatabase (or perhaps SQLiteOpenHelper) instances? You can only have one connection to the database otherwise you'll get the errors you've experienced. SQLiteDatabase itself is thread safe, so you can access it concurrently.

这篇关于&QUOT;错误code 5:数据库已锁定&QUOT;使用ContentProvider的时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆