我有两个SQLite数据库文件:分期SQLite数据库文件可靠
data.db
(生产)data.db.tmp
(分期)
两个数据库都在WAL journaling mode。此外,暂存数据库处于独占锁定模式(使用PRAGMA locking_mode
)与单个读写器,而生产数据库处于共享/正常锁定模式,并且具有多个读取器且不具有写入器。
在任何给定时间点,文件结构可能是这样的:
data.db
data.db-shm
data.db-wal
data.db.tmp
data.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'
:
此前的文件实用程序的版本 '4.0', 'MV' 可以移动文件系统之间只有经常 文件。例如,现在“mv”可以将包括来自一个分区 的特殊设备文件的整个 目录层次结构移动到另一个分区。它首先使用'cp -a' 用于复制请求的目录和文件的相同代码,然后(假设复制 成功)它将删除原始文件。如果复制失败,则复制到目标分区的部分 将被删除。
重命名整个文件夹也不是原子的。
我该怎么做才能使这个分期过程可靠?
一些补充说明:
- 我的客户端API是PHP/PDO,所以我要在SQLite online backup C interface
- 数据库不能访问是几个GB的大小,所以一些在 - 存储器解决方案可能不是可行
这件事发生在我身上,但我不确定它会是那么简单。在临时数据库上将日志模式更改为DELETE是否足以让生产连接检测到它不再需要'-wal'和'-shm'文件? –
我的担心是,如果我需要将** production **数据库的日志模式更改为DELETE,读者可能会连接到它并因此将日记模式再次更改回WAL(在mv发生之前)。解决这个问题的一种方法是,将锁定模式设置为在两个数据库上独占,但这会破坏未来的读者,并且 - 我不确定 - 如果在特定时间有任何具有共享锁的活动读取器,则可能会失败。 –
活跃阅读者将继续阅读旧文件;他们只有在重新打开新文件时才会看到新文件,即使用新的数据库连接。 –