2

我正在尝试从每隔 5 分钟运行的 cronjob 备份我的 sqlite 数据库。数据库是“实时的”,因此在我要执行备份时正在运行查询。

我想确定,当我备份它时,数据库处于良好状态,以便我可以依赖备份。

我目前的策略(伪代码):

function backup()
{
    #try to acquire the lock for 2 seconds, then check the database integrity
    sqlite3 mydb.sqlite '.timeout 2000' 'PRAGMA integrity_check;'
    if (integrity is ok and database was not locked)
    {
        #perform the backup to backup.sqlite
        sqlite3 mydb.sqlite '.timeout 2000' '.backup backup.sqlite'

        if (backup could be performed)
        {
            #Check the consistency of the backup database
            sqlite3 backup.sqlite 'PRAGMA integrity_check;'
            if (ok)
            {
                return true;
            }
        }
    }

    return false;
}

现在,我的策略存在一些问题:

  • 如果实时数据库被锁定,我会遇到问题,因为那时我无法执行备份。也许交易可以帮助那里?
  • 如果PRAGMA integrity_check;备份和备份之间出现问题,我就完蛋了。

有任何想法吗?sqlite3 .backup顺便说一句,the和 a good old 有什么区别cp mydb.sqlite mybackup.sqlite

[编辑]我在嵌入式系统上运行 nodejs,所以如果有人建议使用一些 ruby​​ 包装器的sqlite 在线备份 api - 没有机会;(

4

2 回答 2

4

如果要在查询运行时进行备份,则需要使用备份 API。该文档有一个正在运行的数据库的在线备份示例(示例 2)。我不了解 Ruby 参考,您可以将其集成到您的程序中,或者将其作为一个在实际应用程序之外运行的小型 C 程序来执行——我都做过。

对备份进行显式完整性检查是多余的。备份 API 保证目标数据库是一致的和最新的。(硬币的另一面是,如果您在备份运行时过于频繁地更新数据库,备份可能永远不会完成。)

可以使用“cp”进行备份,但不能备份正在运行的数据库。您需要在整个备份期间拥有一个独占锁,因此它并不是真正的“实时”。您还需要小心复制所有 sqlite 的临时文件以及主数据库。

我希望 sqlite3 ".backup" 命令使用备份 API。

于 2013-04-19T13:49:24.290 回答
3

如果您无法使用备份 API,则必须使用另一种机制来防止在复制数据库文件时对其进行修改。

使用BEGIN IMMEDIATE开始事务:

在 BEGIN IMMEDIATE 之后,没有其他数据库连接能够写入数据库或执行 BEGIN IMMEDIATE 或 BEGIN EXCLUSIVE。但是,其他进程可以继续从数据库中读取。

于 2013-04-19T19:20:37.957 回答