2011-06-03 113 views
3

我在10.6中編寫了一個簡單的Cocoa應用程序。在程序運行時(程序定期保存到數據存儲區),我停電,並且我的程序使用的sqlite文件已經以某種方式損壞。停電後的sqlite存儲中的核心數據損壞

我創建一個標準的方式被管理對象上下文:

managedObjectContext = [[NSManagedObjectContext alloc] init]; 
[managedObjectContext setPersistentStoreCoordinator: coordinator]; 

,通常一切都很好,但是這一次,讀取對象時:

NSLog(@"%@",dir.files); 

我得到:

2011-06-03 11:33:38.079 Backup Check[1927:3c03] Relationship fault for 
(<NSRelationshipDescription: 0x100562230>), name files, isOptional 1, 
isTransient 0, entity Directory, renamingIdentifier files, validation 
predicates ( 
), warnings (
), versionHashModifier (null), destination entity File, inverseRelationship 
directory, minCount 0, maxCount 0 on 0x10058bbc0 

我在命令行嘗試了sqlite3工具,很多東西都可以正確讀取,但是對於som Ë表讀我得到了一堆表項,然後:

SQL error: database disk image is malformed 

我猜測,在保存時正好發生了停電。我有幾個問題: 1)我該如何檢測/恢復?現在我沒有收到任何我創建對象上下文時可以看到的錯誤。此外,許多表格都沒有錯誤,只有在深入研究子表格時,我纔會發現這種關係錯誤。我無法檢查null,因爲一個對象正在被返回 - 它只是不是NSSet。這是某種關係故障對象。 2)我如何採取措施預防未來的腐敗?在創建託管對象上下文時是否有一種簡單的方法來檢查一致性,如果檢測到損壞,我可以回滾到舊版本?在應用程序支持目錄中,我只看到一個文件,這是損壞的數據庫。

回答

3

沒有任何API工具可以修復損壞的SQL存儲。它簡直是如此罕見的事件,沒有多少意義。我在過去5年以上看到了一個損壞的Core Data SQL商店。

從NSLog獲取的打印輸出不會指出錯誤。使用「故障」一詞並不意味着在這種情況下的錯誤,而是表明它是故障對象。故障是代表關係中管理對象的輕量級「虛影」對象故障用於維護對象圖的完整性,而無需加載與每個對象關聯的所有數據。獲取會默認返回關係錯誤,因此在關係中查看它們是正常的,並不表示錯誤。

SQL錯誤指示數據庫的模式已損壞。沒有自動化的方法來解決這個問題。您只需wh出您的瘋狂的低級SQL技能並將數據庫重新拼接在一起即可。這樣做很不值得。 (首先,你必須解開蘋果公司沒有記錄的模式)。

最後,沒有辦法保護任何基於文件的持久性存儲器停電。如果寫入硬件出現故障,即使是大鐵桿也會被丟棄。 (這就是服務器UPS系統如此重要的原因。)不管你做什麼,在某個時刻你都有寫硬件或發送數據的硬件,如果硬件出現故障,那麼在軟件中你就無能爲力了。添加更多寫入製作兩份或更多份,只是增加了更多的中斷點。

這些類型的腐敗非常罕見,所以我不打算試圖對付它們。但是,如果你偏執狂,一個簡單的部分解決方案是定期將存儲文件複製到備份中,以便至少可以恢復到以前的版本,而不必從頭開始。

+0

感謝您的信息。我不在乎修理這個特別的商店,而是防止未來發生。有一件事我仍然想知道 - 我有一個名爲Directory的管理對象,帶有一個類成員「files」。我的理解是,當我到NSLog的類成員,它會被提取。但在這裏,當我真正嘗試將消息傳遞給NSSet「.files」時,它會使程序崩潰。我怎麼可以在這裏放一些代碼來檢查並看看ghost對象是否實際上不指向任何東西,因此我可以重建coredata存儲? – Ryan 2011-06-03 19:55:07

+0

不,一個關係中的對象將被默認取爲故障。這是爲了防止級聯加載大量的對象。當您訪問故障表示的對象的屬性時,故障只會轉換爲管理對象(行話中的「故障」)。看到「關係錯誤」簡單並不是錯誤。將故障看作「佔位符對象」。 – TechZen 2011-06-03 20:17:21