"故障21(内存不足)"执行一些SQLite的操作时,故障、操作、内存不足、QUOT

2023-09-06 18:29:27 作者:茅坑拉屎脸朝外的汉子

我的应用同步与亚马逊的服务器上存在的外部数据库本地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.

下面是执行同步code:

Here is the code that performs the synchronization:

@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(+表是否存在删除表);

行的目的是要删除临时表,如果由于某种原因,该应用已事先崩溃和$ P $被丢弃,因为它通常会这么做pvented表。我注意到,如果该表被单独留在家中,应用程序会当它试图创建新表具有相同名称的崩溃。

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.

现在的问题解决了。