SQLite 异常:数据库被锁定问题 [英] SQLite exception: Database is locked issue

查看:95
本文介绍了SQLite 异常:数据库被锁定问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Android 应用程序中的 SQLite 数据库出现问题.它似乎经常发生,我无法重现,但这是 Android Market 提供的报告.

I'm having an issue with my SQLite database inside an Android app. It seems to happen every so often and I cannot reproduce it, but this is the report the Android Market gives.

基本上,我首先有一个启动画面活动,首先检查所有需要的数据是否在数据库中.如果没有,它将在异步线程中安装数据并关闭数据库连接.

Basically I have first a splash screen activity that starts by checking if all the needed data is in the database. If not, it will install the data in a asynchronous thread and close the db connection.

然后才可以启动主要活动,它也会打开和读取/写入数据库.

Then and only then can the main activity be started, which also opens and reads/writes the database.

此代码从启动画面活动的 onCreate 方法执行:

This code is executed from the onCreate method of the splash screen activity:

dbWord = new WordDBAdapter(this, myUI);
dbWord.open();
if (dbWord.isDataInstalled()) {
    dbWord.close();
    databaseInstalled = true;
    clickToStartView.setText(myUI.PRESS_TO_START);
    clickToStartView.startAnimation(myBlinkAnim);
} else {
    // If not, try to install in asynchronous thread
    progressDialog = new ProgressDialog(this);
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    progressDialog.setMessage(myUI.INSTALLING_DB);
    progressDialog.setCancelable(false);
    new InstallDBData().execute("");
}

异步线程的代码是:

private class InstallDBData extends AsyncTask<String, Integer, Integer> {

    @Override
    protected Integer doInBackground(String... arg0) {
        progressDialog.setProgress(0);
        dbWord.installData(0, getApplicationContext());
        progressDialog.setProgress(20);
        dbWord.installData(1, getApplicationContext());
        progressDialog.setProgress(40);
        dbWord.installData(2, getApplicationContext());
        progressDialog.setProgress(60);
        dbWord.installData(3, getApplicationContext());
        progressDialog.setProgress(80);
        dbWord.installData(4, getApplicationContext());
        progressDialog.setProgress(100);
        return 1;
    }

    protected void onPreExecute() {
        progressDialog.show();
    }

    protected void onPostExecute(Integer x) {
        dbWord.close();
        progressDialog.hide();
        databaseInstalled = true;
        clickToStartView.setText(myUI.PRESS_TO_START);
        clickToStartView.startAnimation(myBlinkAnim);
    }
}

这些是 WordDBAdapter 类的重要部分,也被主要活动使用:

These are important parts of the WordDBAdapter class, which is also used by the main activity:

public class WordDBAdapter {
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;

    public WordDBAdapter open() throws android.database.SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        mDbHelper.close();
    }
    ...
}

我收到以下异常,它们相似但有不同的信息:

I'm getting the following exceptions, which are similar but have a different message:

第一类错误信息:

java.lang.RuntimeException: Unable to start activity 
  ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}: 
  android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1830)
....
Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1870)
at android.database.sqlite.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:602)

第二种错误信息:

java.lang.RuntimeException: Unable to start activity 
  ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}: 
  android.database.sqlite.SQLiteException: database is locked
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
....
Caused by: android.database.sqlite.SQLiteException: database is locked
at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987)
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1855)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)

我真的不想创建一个 ContentProvider,因为如果有更简单的解决方案可用,我相信它会矫枉过正.此外,只有该应用程序可以访问数据库.

I would really like to not have to create a ContentProvider, because I believe its overkill if a simpler solution is available. Also, only this application has access to the database.

有关如何解决此问题的任何建议?

Any suggestions on how this can be fixed?

推荐答案

经过一些努力,我做到了(我的应用程序在 android 2.3 之前一直在完美运行,但是当我以前在 HoneyComb 平板电脑上运行它时出现 db lock 错误).
我确实使用了信号量(在关键部分使用锁).

After doing some effort I did it (My app was working on perfect till android 2.3 but got db lock error when I used to run it on HoneyComb tablet).
I did using Semaphores (using lock in critical sections).

示例 1

public class DbExp extends SQLiteOpenHelper{
    public static String Lock = "dblock";
    private static final String DATABASE_NAME = "db.db";
    private static final String TABLE_NAME = "table_name";

    public void delete(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = getWritableDatabase();
            db.delete(TABLE_NAME, null, null);
            db.close();
        }
    }

    public void insert(){
        synchronized(Lock) {
            SQLiteDatabase db  = getWritableDatabase();
            db.insert(TABLE_NAME, ..., ...);
            db.close();
        }
    }

}

示例 2

public class DB {
    public static String Lock = "dblock";
    private static final String DATABASE_NAME = "db.db";
    private static final String TABLE_NAME = "table_name";

    public void delete(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
            db.delete(TABLE_NAME, null, null);
            db.close();
        }
    }

    public void insert(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
            db.insert(TABLE_NAME, ..., ...);
            db.close();
        }
    }


}

希望这对未来的任何人都有帮助:)

Hope this would help Anyone in future :)

这篇关于SQLite 异常:数据库被锁定问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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