Я должен поместить свою веру в транзакции SQLite для предотвращения повреждения файла?

Короткая версия

Если мой процесс завершается посреди транзакции, или в то время как SQLite фиксирует транзакцию, каковы возможности, что файл базы данных будет поврежден?

Долгая версия

Мое приложение использует базу данных SQLite для устройства хранения данных (непосредственно, не через Базовые Данные). Я работаю над новой версией приложения, которое потребует обновления схемы базы данных. На запуске приложение проверит базу данных и, если этому будет нужно обновление, выполните серию SQL-операторов, чтобы сделать так.

В зависимости от объема данных в базе данных обновление может быть длительным (на порядке секунд), таким образом, я должен рассмотреть возможность, что процесс может быть завершен, прежде чем обновление завершается. (Для контекста это на iPhone, где процессор является медленным и приложение, может быть завершено входящим телефонным вызовом.) Я, конечно, перенесу SQL-операторы обновления в транзакцию. Этого будет достаточно, чтобы гарантировать, что база данных не будет повреждена?

Я предполагаю, что транзакции работают, как рекламируется, и что, если процесс завершается посреди транзакции, файл будет в порядке. Но я также предполагаю, что существует окно времени во время ФИКСАЦИИ, где что-то может пойти не так, как надо.

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

В ходе исследования этого вопроса я начал читать "Атомарную Фиксацию В SQLite", который является большим количеством детали, чем я, вероятно, должен знать, но даю мне веру, что я не должен пересматривать способность SQLITE защитить файл базы данных. Но я все еще хотел бы получить известие от Переполнения стека: действительно ли транзакция достаточно хороша, или я должен быть более осторожным?

6
задан benzado 8 January 2010 в 00:22
поделиться

2 ответа

.. Оператор формирует диапазон слева направо - если правое значение больше или равно левому. Кроме того, в Perl индексация массива начинается с нуля.

Как насчет этого?

@slice = @rainbow[0..$#rainbow-5];

$ # массив дает индекс последнего элемента в массиве.

-121--1596006-

Здесь возникает вопрос:

  • Почему откат по сценарию должен быть предпочтительнее полного восстановления базы данных из резервной копии непосредственно перед модернизацией?

Я могу придумать несколько причин:

  1. База данных очень большая - скажем, несколько сотен ГБ - и ваша компания не может позволить себе простои и/или административные издержки, которые будут связаны с полным восстановлением.

  2. Была введена ошибка, которая не была обнаружена до недели или двух в производстве. Если ты никогда не испытывал этого раньше, тебе повезло. Если в новой базе данных есть транзакции на неделю, можно забыть просто о восстановлении из резервной копии.

  3. Ошибка была обнаружена только через месяцев до выпуска. Другими словами, у вас больше нет резервного копирования, и вы официально находитесь в режиме борьбы с повреждениями/аварийного восстановления. Я никогда этого не испытывал, но слышал истории. Это страшная мысль - как вы отмените весь ущерб, который был нанесен? В этом случае ваше понижение может быть не идеальным, но это все равно может быть лучше, чем альтернатива.

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

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

Могут быть и другие причины для понижения скриптов - это только за пределами моей головы.

-121--4631876-

Я прочитал документ Atomic Commit in SQLite . Если вы действительно хотите понять, что происходит, это может быть не слишком, но в двух словах, транзакция идет так:

  1. Заблокировать файл базы данных
    • Создание журнала отката
      1. Определите, какие части файла базы данных будут изменяться
    • Запись копий этих страниц в файл журнала
    • Запись заголовка файла журнала
    • Запись предполагаемых изменений в файл базы данных
    • Удаление журнала отката ( ЭТО COMMIT )

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

Если бы это был я, я бы доверял сделкам. С таким количеством пользователей SQLite, даже во встроенных приложениях, я думаю, что сбои фиксации транзакций были бы очень горячей темой по всей сети, если бы они работали неправильно.

7
ответ дан 16 December 2019 в 21:40
поделиться

Вы используете CoreData с бэкэндом SQLite? Если да, то я на самом деле считаю, что лучший способ решить эту проблему - это создать два отдельных NSManagedObjectContexts (только для чтения и редактирования). Когда процесс завершится, просто сохраните контекст "редактирования", и тогда эти два контекста будут синхронизированы. Если что-то произойдёт во время вашей операции, контекст редактирования не будет сохранён, так что всё будет в порядке.

1
ответ дан 16 December 2019 в 21:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: