1

在 HTC Desire(android 版本 2.3.3)上运行我的应用程序我注意到调用以下函数时内存使用量增加:

private static final String TABLE_MODULES = "tbl_module1";
private static final String MOD1_INCLUDE = "mod1_include";

private void setItemInclude (int idx, boolean include)
{
    String incString = "";
    if (include)
        incString = "true";
    else
        incString = "false";

    ContentValues args = new ContentValues();
    args.put(MOD1_INCLUDE, incString);
    database.update(TABLE_MODULES,args,"_id="+idx,null);
}

其中 database 是 SQLiteDatabase 类型,是通过调用 dbHelper.getWritableDatabase() 获得的,其中 dbHelper 派生自 SQLiteOpenHelper 并使用应用程序上下文进行实例化。

我得到了所需的更新,但是当我检查我的应用程序的数据使用情况时,每次调用它似乎增加了大约 60KB,并且除非调用 dbHelper.close() 否则不会释放。多次调用此函数会导致 SQLiteDiskIOException。

我试过database.rawQuery()了,它也能正确更新,但同样会挂在内存上。

String updateQuery = "UPDATE " + TABLE_MODULES + " SET MOD1_INCLUDE = " + "'" + incString + "'" + " WHERE _id ='" + idx + "'";

Cursor cursor = database.rawQuery(updateQuery, null);
cursor.moveToFirst();
cursor.close();

在 Asus (android 4.0.3) 和 Orange San Francisco (android 2.1.update1) 上运行相同的代码没有这个问题。

getWritableDatabase从活动中调用,onCreate()生成的数据库在onDestroy(). 我认为在活动期间保持数据库打开是可以的。关于原因的任何想法?

4

2 回答 2

0

文档很清楚。

WAL 日志模式使用预写日志而不是回滚日志来实现事务。

在您的情况下,听起来自动检查点要么未配置,要么无法正常工作。您可能不想关闭日记功能,因为它会导致数据丢失。

于 2013-08-15T19:19:57.660 回答
0

我找到了导致问题的原因。

在 HTC 上,每次database.update()调用都会在应用程序的数据库目录中更新一个临时文件。该文件的扩展名为.sqlite-wal。这个文件在每次调用时都会变大(增加 60KB),并且只有在我关闭数据库时才会被删除。

华硕还会创建一个临时文件,但扩展名为.sqlite-journal。该文件也会在每次update()调用时更新,但一旦事务完成,文件的大小就会减小到零。因此,不会导致内存问题。

我不确定 Journal 和 Wal 之间有什么区别,但相信它们都与事务失败后回滚数据库有关。我已经使用以下代码解决了内存问题,它关闭了日志/wal 功能。

Cursor cursor = database.rawQuery("PRAGMA journal_mode=OFF", null);
cursor.moveToFirst();
cursor.close();

打开数据库后调用它似乎可以防止创建这些临时文件。

但是,我不相信这是一个好主意。我很惊讶没有发现其他人报告此问题,并想知道是否将数据库打开准备好进行多个事务是否被认为是不好的做法?我是 SQL 新手,在数据库方面的经验相当有限。

于 2012-12-24T00:00:38.760 回答