Коррупция основных данных

Несколько клиентов для моего iPhone-приложения испытывают повреждение хранилища Core Data (предположим, так как ошибка "Не удалось сохранить в хранилище данных: операция не может быть завершена" (Cocoa ошибка 259.) ")

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

Я предположил, что API-интерфейсы Core Data/SQLlite используют атомные операции и невосприимчивы к коррупции, за исключением случаев, когда основная файловая система испытывает коррупцию.

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

Изменить:

Также возникает ошибка: "База данных на /var/mobile/Applications//Documents/foo.sqlite повреждена. Код ошибки SQLite 11, образ диска базы данных искажен".

Ответ 1

Это происходит со мной, когда я вручную перезаписал свой Base.sqlite без удаления Base.sqlite-wal и Base.sqlite-shm. Действительно, эти файлы являются новыми функциями SQLite 3.7, возможно, добавлены в iOS 7.

Чтобы устранить проблему, я удалил Base.sqlite-*, и sqlite восстановил их из моей новой базовой версии.

Ответ 2

Ошибка, которую вы получаете, определяется в Foundation.h

NSFileReadCorruptFileError = 259,//Ошибка чтения (поврежденный файл, неправильный формат и т.д.)

Я никогда не сталкивался с ним с фактическим магазином, но я ударил что-то похожее с плохими разрешениями (на Mac.) Я не видел, чтобы кто-либо упоминал аналогичную ошибку онлайн. Системы предотвращения ошибок в Core Data довольно надежны.

Я бы предположил, что самый простой способ создать это - отправить постоянное хранилище, чтобы посмотреть на неправильный файл, например, случайно настроить его в текстовом файле. Если он ожидает SQL-хранилище, но находит что-то еще, он будет жаловаться, что файл поврежден. Это просто выстрел в темноте.

Изменить

Это трудно будет отследить, потому что такие ошибки настолько редко встречаются в Core Data, что нет никаких инструментов для поиска проблемы.

Я бы порекомендовал:

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

Ответ 3

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

Ответ 4

Для ясности, используя Xcode 7.2.1, хранилище данных SQLite, график объектов Core Data для прототипа.

Моя проблема была подробно описана терминалом Xcode следующим образом:

CoreData: error: (11) Неустранимая ошибка. База данных по /Пользователи/etc/Library/Developer/CoreSimulator/Devices/etc/data/Контейнеры/Данные/Приложение/etc/Library/Поддержка приложений /com.etc.etc/etc.sqlite повреждена. Код ошибки SQLite: 11, "образ диска базы данных искажен".

Фактически мое приложение смогло загрузить и прочитать данные SQLite, но не удалось сохранить.

Этот ответ от пользователя SO разработанного, имел смысл для меня. При использовании Simulator я был достаточно уверен, что прервал операцию сохранения в контексте управляемого объекта с частной очередью concurrency type NSPrivateQueueConcurrencyType.

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

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

Примечания по этому опыту:

  • В делегате приложения в соответствии с протоколом UIApplicationDelegate - (void)applicationWillResignActive:(UIApplication *)application, если ваш контекст управляемого объекта hasChanges обязательно включите метод сохранения базы данных;
  • Если вы используете более одной очереди, используйте кнопку "Домой", чтобы вызвать метод делегата в пункте 1, прежде чем нажать кнопку "Стоп" в Xcode;
  • Восстановить поврежденный файл базы данных. Я разработал решение, подробно описанное ниже, из ответа, изложенного на этой веб-странице. Исправление ошибки SQLite "Образ диска базы данных искажен" .

Метод восстановления файла базы данных SQLite:

  • Открыть терминал [команды терминала /sqlite ];
  • Перейдите к соответствующему местоположению файла [ cd];
  • В целях резервного копирования сделайте копию файла базы данных "malformed" (например, dbMalFormedBU.sqlite) (который может быть удален позже, если восстановление выполнено успешно) [cp];
  • Чтобы быть уверенным, удалите файлы dbMalFormed.sqlite-shm и dbMalFormed.sqlite-wal [rm];
  • Откройте свой файл базы данных "неправильный" [sqlite3 dbMalFormed.sqlite];
  • Клонирование файла базы данных [ .clone dbMalFormedNew.sqlite];
  • Выход из SQLite3 [ .exit];
  • Удалить старый файл с ошибкой [ rm dbMalFormed.sqlite);
  • Переименуйте новый файл базы данных в ранее используемое имя [ mv dbMalFormedNew.sqlite dbMalFormed.sqlite].

Ответ 5

Вы когда-нибудь взаимодействуете с базой данных с помощью API sqlite? Или вы использовали какие-либо инструменты, отличные от Apple, для создания вашей базы данных семян?

Ответ 6

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

Ответ 7

Я испытал эту ошибку при попытке получить постоянный координатор хранилища.

Многопоточность была проблемой в моем случае. Исправлено его обертывание всего метода блоком @synchronized(self) {}.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    @synchronized(self) {

    // Quickly return persistent store coordinator if available
    if (__persistentStoreCoordinator != nil) {
        return __persistentStoreCoordinator;
    }

    // Persistent store coordination initialization, to be performed once
    // ...

    }
    return _persistentStoreCoordinator;
}

Ответ 8

Недавно я столкнулся с этой проблемой. В моем случае я выполнял поиск и итерацию по объектам для преобразования данных в XML и KML. Затем я создавал обработчик электронной почты и прикреплял файлы. Затем я обновил бы поле в объектах и, наконец, сохранил бы в хранилище резервных копий (SQL Lite). Обработанный штраф в 3.x. В 4.x он сломался.

С моей стороны было глупо выполнять всю обработку электронной почты, прежде чем изменять и сохранять БД. Перемещение всего нестандартного кода в точку после сохранения устраняет эту проблему.

Эта проблема полностью повредит SQL DB. В моем случае ошибка:

 File at path does not appear to be a SQLite database