У меня есть два файла базы данных 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» для копирования запрошенных каталогов и файлов, затем (при условии, что копия выполнена успешно) удаляет оригиналы. Если копия завершается с ошибкой, удаляется часть, скопированная в целевой раздел.
Переименование целых папок также не является атомарным.
Что я могу сделать, чтобы сделать процесс промежуточного этапа надежным?
Некоторые дополнительные замечания: