【问题标题】:Android: Copy db file not working after update to data is performed when wal existsAndroid:当 wal 存在时,在执行数据更新后复制 db 文件不起作用
【发布时间】:2013-01-28 08:34:28
【问题描述】:

我有一个具有备份和恢复功能的应用程序。单击要备份的按钮会将 db 文件复制到外部存储。单击恢复按钮将从外部存储中获取文件(如果存在)并将其复制到应用程序中,并用备份数据库文件覆盖现有数据库。

我在对表执行更新时遇到了这个问题。用数据更新表后,更新数据的数据库不会复制到外部存储中,或者如果我在更新后尝试恢复,则不会复制文件。

当一个项目被保存时,数据库被打开,然后调用下面的函数进行更新,然后数据库被关闭。

public void saveItem(int ItemID, int ItemNumber, String itemnote) 

{

        ContentValues args = new ContentValues();
        args.put("ItemNote", itemnote);
    mDb.update("Items", args, "ItemID =" + Item+" and ItemNumber ="+ItemNumber, null);

}

更新发生后,是什么阻止了db文件被复制?

我正在使用以下代码将数据库备份导入应用程序。同样,这一切都在执行更新语句之前起作用。提前致谢。

importdb.setOnClickListener(new View.OnClickListener(){ public void onClick(查看 arg0) {

            final File DATA_DIRECTORY_DATABASE = getDatabasePath("MyDB");

            final File DATABASE_DIRECTORY = new File(Environment.getExternalStorageDirectory(),"/MyApp");
            final File IMPORT_FILE = new File(DATABASE_DIRECTORY,"MyDB");

            File exportFile = DATA_DIRECTORY_DATABASE;

            File importFile = IMPORT_FILE;


            try {
                exportFile.createNewFile();
                copyFile(importFile, exportFile);
                Log.i("Import", "Succesfull");

            } catch (IOException e) {
                e.printStackTrace();

            }       




        }

    });

private static void copyFile(File src, File dst) throws IOException {
    FileChannel inChannel = new FileInputStream(src).getChannel();
    FileChannel outChannel = new FileOutputStream(dst).getChannel();
    try {
        inChannel.transferTo(0, inChannel.size(), outChannel);
    } finally {
        if (inChannel != null)
            inChannel.close();
        if (outChannel != null)
            outChannel.close();
    }
}

【问题讨论】:

  • 经过进一步审查和测试,这似乎是特定于设备的问题。我在其他设备上测试没有任何问题。出现此问题的设备是 HTC Droid Incredible。当对数据库进行更新时,我注意到数据库处于 wal 模式(预写日志记录)。我在 db 文件上进行了导出或恢复,我相信它会被 wal 模式覆盖,这就是为什么它的行为不像我想要的那样。关于如何处理 wal 模式的任何建议?

标签: android database copy


【解决方案1】:

我认为数据库版本没有改变,这就是代码无法正常工作的原因。

【讨论】:

  • 为什么需要更改数据库版本?数据库的结构没有变化,数据库没有升级,所以是同一个版本的数据库。正在改变的是数据库中的数据,即表中列中数据的更新。
【解决方案2】:

如果数据库连接没有关闭,那么数据库文件可能仍然被 SQLite 锁定;因此阻止其复制。

如果您使用多个线程,那么即使关闭数据库连接,SQLite 也可能没有时间在第二个线程尝试复制之前关闭数据库并释放锁。

【讨论】:

  • 经过进一步审查和测试,这似乎是特定于设备的问题。我在其他设备上测试没有任何问题。出现此问题的设备是 HTC Droid Incredible。当对数据库进行更新时,我注意到数据库处于 wal 模式(预写日志记录)。我在 db 文件上进行了导出或恢复,我相信它会被 wal 模式覆盖,这就是为什么它的行为不像我想要的那样。关于如何处理 wal 模式的任何建议?
  • 好吧,你为什么首先使用 WAL 模式?在关闭事务之前,必须将 WAL 文件写回数据库文件;延长释放文件锁定所需的时间。
【解决方案3】:

在对不同设备进行大量测试并查看日志文件之后。发现在某些设备上,数据库处于预写日志记录模式 (wal)。这不是所有设备,但在我的一个测试设备 HTC Droid Incredible 上,wal 已启用,而在 kindle fire 上,wal 未启用。

在未启用 wal 的设备上,没有问题。在带有 wal 的设备上,数据的导入和导出无法正常工作,因为实际的 db 文件不是最新的,因为任何更改都驻留在 wal 文件中,并且在 wal 的检查点被命中之前不会提交到 db 文件。

为确保导入和导出功能正常工作,我需要数据库包含最新信息。为此,需要运行 sqlite 语句来执行 wal 检查点,该检查点会将所有信息提交到 db 文件。

在运行导出或导入功能之前,执行以下sqlite命令以启动检查点并清除wal并将更改提交到数据库。

PRAGMA wal_checkpoint

调用检查点后功能正常

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多