Несколько клиентов для моего iPhone-приложения испытывают повреждение хранилища Core Data (предположим, так как ошибка "Не удалось сохранить в хранилище данных: операция не может быть завершена" (Cocoa ошибка 259.) ")
Кто-нибудь еще сталкивался с коррупцией в магазине? Я беспокоюсь, так как я стремился скопировать обновление, которое выполняет миграцию схемы, и я беспокоюсь, что это вызовет еще больше проблем.
Я предположил, что API-интерфейсы Core Data/SQLlite используют атомные операции и невосприимчивы к коррупции, за исключением случаев, когда основная файловая система испытывает коррупцию.
Есть ли способ уменьшить/предотвратить коррупцию и способ воспроизвести коррупцию, чтобы я мог проверить это (я до сих пор не увенчался успехом).
Также возникает ошибка: "База данных на /var/mobile/Applications//Documents/foo.sqlite повреждена. Код ошибки SQLite 11, образ диска базы данных искажен".
Это происходит со мной, когда я вручную перезаписал свой Base.sqlite
без удаления Base.sqlite-wal
и Base.sqlite-shm
. Действительно, эти файлы являются новыми функциями SQLite 3.7, возможно, добавлены в iOS 7.
Чтобы устранить проблему, я удалил Base.sqlite-*
, и sqlite восстановил их из моей новой базовой версии.
Для ясности, используя 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, которую я сохранил, в то время была причиной этой проблемы.
Я мог бы легко удалить приложение (еще не публичный выпуск), однако я хотел бы понять, по крайней мере, как устранить эту проблему.
Примечания по этому опыту:
- (void)applicationWillResignActive:(UIApplication *)application
, если ваш контекст управляемого объекта hasChanges
обязательно включите метод сохранения базы данных;Метод восстановления файла базы данных SQLite:
cd
];dbMalFormedBU.sqlite
) (который может быть удален позже, если восстановление выполнено успешно) [cp
];dbMalFormed.sqlite-shm
и dbMalFormed.sqlite-wal
[rm
];sqlite3 dbMalFormed.sqlite
];.clone dbMalFormedNew.sqlite
];.exit
];rm dbMalFormed.sqlite
);mv dbMalFormedNew.sqlite dbMalFormed.sqlite
].Также попытайтесь реплицировать ошибку, заполнив диск на устройстве - вы должны получить полную ошибку на диске вместо искажения базы данных, но таким образом можно получить поврежденную базу данных.
Ошибка, которую вы получаете, определяется в Foundation.h
NSFileReadCorruptFileError = 259,//Ошибка чтения (поврежденный файл, неправильный формат и т.д.)
Я никогда не сталкивался с ним с фактическим магазином, но я ударил что-то похожее с плохими разрешениями (на Mac.) Я не видел, чтобы кто-либо упоминал аналогичную ошибку онлайн. Системы предотвращения ошибок в Core Data довольно надежны.
Я бы предположил, что самый простой способ создать это - отправить постоянное хранилище, чтобы посмотреть на неправильный файл, например, случайно настроить его в текстовом файле. Если он ожидает SQL-хранилище, но находит что-то еще, он будет жаловаться, что файл поврежден. Это просто выстрел в темноте.
Это трудно будет отследить, потому что такие ошибки настолько редко встречаются в Core Data, что нет никаких инструментов для поиска проблемы.
Я бы порекомендовал:
Я испытал эту ошибку при попытке получить постоянный координатор хранилища.
Многопоточность была проблемой в моем случае. Исправлено его обертывание всего метода блоком @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;
}
Я испытал "повреждение хранилища основных данных", когда я предварительно загружал базу данных с разделенным потоком (не основным потоком), и было очень сложно найти эту ошибку, поскольку только некоторые из моих клиентов будут разбивать их приложение из-за этого.
Вы когда-нибудь взаимодействуете с базой данных с помощью API sqlite? Или вы использовали какие-либо инструменты, отличные от Apple, для создания вашей базы данных семян?
NSPersistentStoreCoordinator
, NSManagedObjectModel
и друзья.
Недавно я столкнулся с этой проблемой. В моем случае я выполнял поиск и итерацию по объектам для преобразования данных в XML и KML. Затем я создавал обработчик электронной почты и прикреплял файлы. Затем я обновил бы поле в объектах и, наконец, сохранил бы в хранилище резервных копий (SQL Lite). Обработанный штраф в 3.x. В 4.x он сломался.
С моей стороны было глупо выполнять всю обработку электронной почты, прежде чем изменять и сохранять БД. Перемещение всего нестандартного кода в точку после сохранения устраняет эту проблему.
Эта проблема полностью повредит SQL DB. В моем случае ошибка:
File at path does not appear to be a SQLite database