本文介绍了"失败 21(内存不足)"执行一些 SQLite 操作时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用将其本地 SQLite 数据库与存在于亚马逊服务器上的外部数据库同步.有时,同步失败并产生以下 logcat 输出:

My app synchronizes its local SQLite database with an external database that exists on Amazon's servers. Occasionally, the synchronization fails and produces this logcat output:

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)

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

When this happens, my app notifies me that synchronization failed, so I ask it to attempt synchronization again, which works about 50-75% of the time.

这是执行同步的代码:

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

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

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

The purpose of the line is to drop the temporary table if, for some reason, the app had crashed beforehand and prevented the table from being dropped as it normally would do so. I've noticed that if that table is left alone, the app will crash when it tries to create a new table with the same name.

为什么我的应用会在这里耗尽内存,我该如何解决?

Why does my app run out of memory here, and what can I do to fix it?

好的,它实际上每隔一次应用与外部数据库同步时发生.

Okay, it actually happens every other time the app syncs with the external database.

推荐答案

原来这个错误是我的应用程序调用这个方法之前的一个编程错误的结果.在调用 syncToTempTable() 之前,我打开了数据库:

Turns out that this error was the result of a programming error before my app made this method invocation. Before I made the call to syncToTempTable(), I opened the database:

SQLiteDatabase db = dbHelper.getWritableDatabase();

紧接着,我想检查本地数据库的修订号.我用来做的方法也打开了数据库(所以基本上我打开了我的数据库两次)然后关闭它(这可能关闭了所有打开的数据库流).因此,我没有意识到我给了 syncToTempTable() 一个封闭的数据库.

Right after this, I wanted to check the revision number of the local database. The method that I used to do that also opened the database (so basically I opened my database twice) and then closed it (which likely closed all open streams to the database). Because of this, I didn't realize that I was giving syncToTempTable() a closed database.

问题现已解决.

这篇关于&amp;quot;失败 21(内存不足)&amp;quot;执行一些 SQLite 操作时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 18:49