【发布时间】:2013-10-18 11:00:52
【问题描述】:
我有两个 SQLite 数据库文件:
-
data.db(生产) -
data.db.tmp(暂存)
两个数据库都在WAL journaling mode。此外,暂存数据库处于独占锁定模式(使用PRAGMA locking_mode),只有一个读取器/写入器,而生产数据库处于共享/正常锁定模式,有多个读取器,没有写入器。
在任何给定时间点,文件结构可能如下所示:
data.dbdata.db-shmdata.db-waldata.db.tmpdata.db.tmp-wal
有时,我想用临时数据库替换生产数据库 - 最好不要破坏现有的 [生产] 阅读器,更重要的是,不要损坏数据库。
我最初(幼稚)的想法是一个简单的mv data.db-tmp data.db,但是因为有多个相关文件,单个重命名并不能保证原子性和一致性。然后我想到了做一个支撑mv:
mv data.db{.tmp,.tmp-wal} data{.db,.db-wal}
我不知道上述是否是原子操作,但考虑到 *-shm 和 *-wal 文件的瞬态性质,它不会很好地工作:如果 data.db.tmp-wal 不存在,则移动将失败(我认为!)并且可能存在的 data.db-shm 对应对象没有原子操作。
根据info coreutils 'mv invocation':
在fileutils '4.0' 版本之前,'mv' 只能移动常规 文件系统之间的文件。例如,现在 'mv' 可以移动整个 目录层次结构,包括来自一个分区的特殊设备文件 给另一个。它首先使用“cp -a”使用的一些相同代码 复制请求的目录和文件,然后(假设复制 成功)它会删除原件。如果复制失败,则该部分 复制到目标分区的文件被删除。
重命名整个文件夹也不是原子的。
我可以做些什么来使这个暂存过程可靠?
一些补充说明:
- 我的客户端 API 是 PHP/PDO,所以我无法访问 SQLite online backup C interface
- 数据库大小为数 GB,因此某些内存解决方案可能不可行
【问题讨论】:
标签: php sqlite atomic corruption