Должен ли я доверять транзакциям SQLite, чтобы избежать повреждения файлов? - PullRequest
6 голосов
/ 06 января 2010

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

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

Длинная версия

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

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

Я предполагаю, что транзакции работают так, как объявлено, и что если процесс завершится в середине транзакции, файл будет в порядке. Но я также предполагаю, что во время COMMIT есть время, когда что-то может пойти не так.

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

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

Ответы [ 2 ]

7 голосов
/ 08 января 2010

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

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

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

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

1 голос
/ 06 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...