何时可以安全地复制当前打开的SQLite数据文件?

时间:2014-04-09 20:37:04

标签: qt sqlite

我有一个应用程序,它在本地文件系统上的文件上使用QSQLITE驱动程序和QSqlDatabse。我想写一个备份函数,它将保存数据库的快照。

简单地复制文件似乎是一种明显,简单的方法,但我不确定这样做是否安全。

应用程序在定义明确的点修改数据库。每次都会创建,使用并立即销毁新的QSqlQuery对象。明确锁定/刷新是一种可接受的解决方案,但Qt API似乎没有公开这一点。

我无法找到有关Qt何时将数据库提交到磁盘的文档。我想QSqlDatabase析构函数会这样做,但即便如此,我也不知道(在Windows或Linux上)复制文件是否会导致最近的更改被复制(相反,仅限于此)那些已经在文件系统期刊中完成的更改)。有人可以确认或否认吗?如果在执行复制之前关闭写文件句柄会有什么不同吗?

也许唯一安全的方法是online copy,但我已经在使用Qt API并且不知道这将如何互动。

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:5)

复制SQLite数据库是微不足道的,但以不会破坏它的方式执行此操作并不是一件容易的事。这将为您提供一个很好的干净备份,确保处于正确的状态,因为在复制过程的中途写入数据库是不可能的。

QSqlQuery qry(db);
qry.prepare( "BEGIN IMMEDIATE;");
qry.exec();

QFile::copy(databaseName, destination);

qry.prepare( "ROLLBACK;");
qry.exec();

在BEGIN IMMEDIATE之后,没有其他数据库连接可以写入数据库或执行BEGIN IMMEDIATE或BEGIN EXCLUSIVE。

答案 1 :(得分:1)

这与Qt几乎没有关系。它与数据库有关。此过程适用于任何符合ACID的数据库,SQLite就是其中之一。

来自http://www.sqlite.org/transactional.html

  

SQLite是Transactional

     

事务数据库是所有更改和查询的数据库   似乎是Atomic,Consistent,Isolated和Durable(ACID)。 SQLite的   实现原子化,一致的可序列化事务   孤立的,持久的,即使交易被中断了   程序崩溃,操作系统崩溃或电源故障   计算机。

这并不意味着您可以复制文件并且它将保持一致。在复制之前,您应该使用块级快照。如果您使用的是Linux,请阅读

http://tldp.org/HOWTO/LVM-HOWTO/snapshotintro.html

程序将是,

  1. 快照
  2. 将数据库从快照复制到备份设备
  3. 删除快照卷
  4. 快照是文件系统的全局“冻结”,由于ACID,它是一致的。文件复制是线性操作,如果不在复制期间暂停所有数据库操作,则无法保证一致。这意味着直接复制对于在线数据库(通常)来说是不安全的。