У меня есть база данных SQLite в моем приложении. Каждый раз, когда приложение изменяет / добавляет строку в DB, приложение явно запускает транзакцию SQLite, выдавая команду BEING TRANSACTION. После обновления / добавления данных в моей базе данных я выдаю команду COMMIT или ROLLBACK, если обновление не удалось. Обычные вещи (https://www.sqlite.org/lang_transaction.html). Все работает идеально, пока не буду не потери мощности.

Проблема каждый раз, когда я выполняющую потери мощности после того, как приложение выполняет {COMMIT, запускает устройство и в конечном итоге запускает приложение, sqlite сохраняет данные, как будто {BEGIN, а COMMIT никогда не произошло вообще ! Почему?

Я также проверил файл базы данных в моем каталоге приложений, он имеет правильные данные. Я также заметил дополнительный файл <mydatabasefilename>-journal в моем каталоге приложений. При проверке, это Temp-файл, используемый SQLite для поддержки отката неполной транзакции, особенно во время мощности потеря.

Опять же, мой COMMIT произошел до потери мощности. Мой файл базы данных (как проверено в моем каталоге приложений) содержит правильные данные. Но почему <mydatabasefilename>-journal содержит более старые данные? Я не понимаю это вообще. Я что-то упускаю здесь?

0
user1506104 26 Сен 2019 в 12:22

1 ответ

Лучший ответ

Какие настройки для PRAGMA synchronous и PRAGMA journal_mode используют вашу базу данных? Они могут быть использованы для контроля точного поведения SQLite по отношению к этим вещам.

Поведение файла {<mydatabasefilename>-journal, содержащее старое содержимое, звучит как журнал Rollback, описанный здесь: https://www.sqlite.org/lockingv3.html#rollback.

Когда процесс хочет изменить файл базы данных (и он не в режиме WAL), он сначала записывает исходное не измененное содержимое базы данных в Rollback Journal. Журнал Rollback - это обычный файл диска, который всегда расположен в том же каталоге или папке в качестве файла базы данных и имеет то же имя, что и файл базы данных с добавлением -journal Suffix. [...]

[...]

Говорят, что журнал Rollback является горячим, если он должен быть откатывается назад, чтобы восстановить целостность его базы данных. Горячий журнал создается, когда процесс находится в середине обновления базы данных, и сбой программы или операционной системы или сбой питания предотвращает завершение обновления. Горячие журналы - это состояние исключения. Горячие журналы существуют, чтобы оправиться от аварий и сбоев питания. Если все работает правильно (то есть, если нет аварий или сбоев питания), вы никогда не получите горячий журнал.

Различные режимы журнала, которые можно найти, описаны здесь: https://www.sqlite.org/ Pragma.html # Pragma_journal_mode

Режим «Удалить журнал» - это нормальное поведение. В режиме удаления журнал Rollback удаляется при заключении каждой транзакции. Действительно, операция удаления - это действие, которое заставляет транзакцию для совершения. (См. Документ под названием Атомный фиксатор в Sqlite для получения дополнительной информации.)

Вы можете попробовать настроить другие настройки для PRAGMA synchronous, см. Эти настройки: https: // www .sqlite.org / pragma.html # Pragma_synchronous

  • Дополнительные (3)

    Extra Synchronous понравился полный с добавлением, что каталог, содержащий журнал Rollback, синхронизируется после того, как этот журнал не отмечен для совершения транзакции в режиме удаления. Дополнительные предоставляют дополнительную долговечность, если фиксатор сопровождается тесном потере мощности.

  • полно (2)

    Когда синхронный полностью (2), двигатель баз данных SQLite будет использовать метод Xync VFS, чтобы убедиться, что весь контент безопасно записан на поверхность диска перед продолжением. Это гарантирует, что сбой операционной системы или сбой питания не повредит базу данных. Полный синхронный очень безопасен, но он также медленнее. Полный - это наиболее часто используемая синхронная настройка, когда не в режиме WAL.

Таким образом, в вашем случае установка PRAGMA synchronous = EXTRA; может сделать то, что вы хотите, но это может прийти по стоимости производительности.

Вы также можете попробовать экспериментировать с PRAGMA journal_mode = WAL;, описанным на https://www.sqlite.org/ Wal.html, в случае, если это лучше работать для вас на потере мощности, с меньшими тяжелыми настройками PRAGMA synchronous.

2
mstorsjo 26 Сен 2019 в 13:15