У меня есть два файла базы данных SQLite:
data.db
( Производство ) data.db.tmp
( data.db.tmp
) Обе базы данных находятся в режиме ведения журнала WAL . Кроме того, промежуточная база данных находится в режиме эксклюзивной блокировки (с использованием PRAGMA locking_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' fileutils 'mv' мог перемещать только обычные файлы между файловыми системами. Например, теперь «mv» может перемещать всю иерархию каталогов, включая специальные файлы устройств из одного раздела в другой. Сначала он использует один и тот же код, который используется «cp -a» для копирования запрошенных каталогов и файлов, затем (при условии, что копия выполнена успешно) удаляет оригиналы. Если копия завершается с ошибкой, удаляется часть, скопированная в целевой раздел.
Переименование целых папок также не является атомарным.
Что я могу сделать, чтобы сделать процесс промежуточного этапа надежным?
Некоторые дополнительные замечания: