执行一些SQLite操作时"失败21(内存不足)"

kib*_*yte 1 sqlite android

我的应用程序将其本地SQLite数据库与Amazon服务器上存在的外部数据库同步.有时,同步失败并产生此logcat输出:

08-15 19:58:38.149: ERROR/Database(343): Failure 21 (out of memory) on 0x0 when preparing 'drop table if exists keymap2'.
08-15 19:58:38.149: ERROR/KeymapDbHelper(343): Error occurred while syncing DB
08-15 19:58:38.149: ERROR/KeymapDbHelper(343): android.database.sqlite.SQLiteException: unknown error: drop table if exists keymap2
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1610)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at lee.medical.icu.dataentry.db.KeymapDbHelper.syncToTempTable(KeymapDbHelper.java:114)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at lee.medical.icu.dataentry.db.KeymapDbHelper.syncDb(KeymapDbHelper.java:84)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at lee.medical.icu.dataentry.MainMenuActivity$DbSyncTask.doInBackground(MainMenuActivity.java:221)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at lee.medical.icu.dataentry.MainMenuActivity$DbSyncTask.doInBackground(MainMenuActivity.java:1)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
08-15 19:58:38.149: ERROR/KeymapDbHelper(343):     at java.lang.Thread.run(Thread.java:1096)
Run Code Online (Sandbox Code Playgroud)

发生这种情况时,我的应用程序通知我同步失败,所以我要求它再次尝试同步,大约有50-75%的时间可以工作.

以下是执行同步的代码:

@SuppressWarnings("unchecked")
private void syncToTempTable(SQLiteDatabase db, String table)
        throws DatabaseMismatchException {
    String awsSql = "select * from " + keymapDb;
    SelectRequest select = new SelectRequest(awsSql);
    SelectResult result;

    Log.d(TAG, "Making request: " + awsSql);
    result = simpleDB.select(select); // Could throw AmazonClientException

    List<Item> items = result.getItems();

    db.execSQL("drop table if exists " + table);
    String tempSql = "create table " + table + " (" +
            C_KEY + " text primary key, " +
            C_NAME + " text)";
    db.execSQL(tempSql);
    Log.d(TAG, "SQL executed: " + tempSql);

    ContentValues cv = new ContentValues();
    for (Item i : items) {
        cv.clear();
        String key = i.getName();
        cv.put(C_KEY, key);

        List<Attribute> attributes = i.getAttributes();
        assert attributes.size() <= 1;
        for (Attribute a : attributes) {
            String name = a.getName();
            String value = a.getValue();

            if ((key.equals(R_INFO) && !name.equals(C_REVISION)) || 
                    (!key.equals(R_INFO) && !name.equals(C_NAME)))
                throw new DatabaseMismatchException("DB not synced because " +
                        "column " + name + " was unexpected");

            cv.put(C_NAME, value);
        }

        db.insert(table, null, cv);
    }
}
Run Code Online (Sandbox Code Playgroud)

114行是 db.execSQL("drop table if exists " + table);

该行的目的是删除临时表,如果由于某种原因,应用程序已事先崩溃并阻止表被删除,因为它通常会这样做.我注意到,如果该表独立,应用程序将在尝试创建具有相同名称的新表时崩溃.

为什么我的应用程序在这里内存不足,我该怎么做才能修复它?

编辑:好的,它实际上发生在应用程序与外部数据库同步的每隔一次.

kib*_*yte 5

事实证明,在我的应用程序进行此方法调用之前,此错误是编程错误的结果.在我打电话之前syncToTempTable(),我打开了数据库:

SQLiteDatabase db = dbHelper.getWritableDatabase();
Run Code Online (Sandbox Code Playgroud)

在此之后,我想检查本地数据库的修订号.我以前做的方法也打开了数据库(基本上我打开了我的数据库两次),然后关闭它(这可能会关闭所有打开的数据库流).因此,我没有意识到我正在提供syncToTempTable()一个封闭的数据库.

问题现在解决了.

  • +1 回答您自己的问题并有礼貌地将其发布以造福他人!干得好。 (2认同)