我的应用程序将其本地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)
当发生这种情况时,我的应用程序会通知我同步失败,所以我要求它再次尝试同步,大约有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);
}
}
第114行是db.execSQL("drop table if exists " + table);
该行的目的是删除临时表,如果由于某种原因,应用程序已事先崩溃并阻止表被删除,因为它通常会这样做。我注意到,如果该表单独存在,应用程序将在尝试创建具有相同名称的新表时崩溃。
为什么我的应用程序在这里耗尽了内存,我该怎么做才能解决它?
编辑:好的,它确实会在应用程序与外部数据库同步时发生。
答案 0 :(得分:5)
事实证明,在我的应用程序进行此方法调用之前,此错误是编程错误的结果。在我致电syncToTempTable()
之前,我打开了数据库:
SQLiteDatabase db = dbHelper.getWritableDatabase();
在此之后,我想检查本地数据库的修订号。我以前做的方法也打开了数据库(基本上我打开了我的数据库两次),然后关闭它(这可能会关闭所有打开的数据库流)。因此,我没有意识到我正在给syncToTempTable()
一个封闭的数据库。
现在问题解决了。