SQLite异常:数据库已锁定问题

San*_*ndy 11 sqlite android locking exception

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

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

然后,只有这样才能启动主要活动,这也会打开并读取/写入数据库.

此代码从启动屏幕活动的onCreate方法执行:

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("");
}
Run Code Online (Sandbox Code Playgroud)

异步线程的代码是:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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();
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我得到以下异常,这些异常相似但有不同的消息:

第一种错误信息:

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)
Run Code Online (Sandbox Code Playgroud)

第二类错误消息:

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)
Run Code Online (Sandbox Code Playgroud)

我真的不想创建一个ContentProvider,因为如果有更简单的解决方案,我相信它有点过分.此外,只有此应用程序才能访问数据库.

关于如何解决这个问题的任何建议?

Mud*_*sar 17

做了一些努力后,我做了它(我的应用程序正在完美,直到android 2.3但我曾经在HoneyComb平板电脑上运行时遇到了数据库锁定错误).
我确实使用了信号量(在关键部分使用锁定).

例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();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

例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();
        }
    }


}
Run Code Online (Sandbox Code Playgroud)

希望这将有助于将来的任何人:)


Sha*_*aun 5

如果您使用Fragments并且它发生了方向更改,那么因为您有两个相同Fragment的实例,并且它们都有自己的某种Db帮助程序类的实例.为了使它工作,你要么必须在方向改变时销毁你的片段并重建它,要么找到一种方法来销毁Db助手类.这仅适用于具有方向问题的片段.我不得不做很多故障排除才能搞清楚,所以希望有人觉得这很有帮助


san*_*h_p 5

这就是我的原因:

插入数据库后,我忘记在函数调用中结束事务。因此,当我尝试从另一个活动插入另一条记录时,我遇到了数据库锁定异常。添加以下语句解决了我的问题。

sqlDB.endTransaction();
Run Code Online (Sandbox Code Playgroud)


Kha*_*war 0

这可能是因为您没有正确打开或创建数据库。如果是这种情况,请尝试一下。

mDb = mCtx.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null);
Run Code Online (Sandbox Code Playgroud)

在DatabaseHelper类中:

public DatabaseHelper(Context aContext)
{       
    mDb = aContext.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null);    
    OpenHelper openHelper = new OpenHelper(aContext, mDb );     
    mDb = openHelper.getWritableDatabase();
}
Run Code Online (Sandbox Code Playgroud)

  • Khawar,我注意到你没有在 DatabaseHelper() 构造函数中调用 `super(context, DATABASE_NAME, null, DATABASE_VERSION);` (2认同)