CoreData版本遷移

來源:互聯網
上載者:User

標籤:

Core Data版本遷移基礎


通常,在使用Core Data的iOS App上,不同版本上的資料模型變更引發的資料移轉都是由Core Data來負責完成的。
這種資料移轉模式稱為Lightweight Migration(可能對於開發人員來說是lightweight),開發人員只要在添加Persistent Store時設定好對應選項,其它的就交付給Core Data來做了:



從命名上可以看出這兩個選項分別代表:自動遷移Persistent Store,以及自動建立Mapping Model。

自動遷移Persistent Store很好理解,就是將資料從一個物理檔案遷移到另一個物理檔案,通常是因為物理檔案結構發生了變化。
自動建立Mapping Model是為遷移Persistent Store服務的,所以當自動遷移Persistent Store選項NSMigratePersistentStoreAutomaticallyOption為@(YES)、且找不到Mapping Model時,coordinator會嘗試建立一份。
其它初始化情境可以參考Initiating the Migration Process。

既然是嘗試建立,便有成功和失敗的不同結果。只有當資料模型的變更屬於某些基本變化時,才能夠成功地自動建立出一份Mapping Model,比如:新增一個欄位;刪除一個欄位;必要欄位轉換成可選欄位;可選欄位轉換成必要欄位,同時提供了預設值等等。

因為可能建立Mapping Model失敗,所以考慮容錯性的話,可以事先判斷下能否成功推斷出一份Mapping Model:



利用如上類方法,如果無法建立一份Mapping Model,則會返回nil,並帶有具體原因。

以上都建立在Core Data能夠自動找到sourceModel和destinationModel的基礎上,如果無法找到對應的兩份Model,則需要開發人員手工建立NSMigrationManager來進行資料移轉(可以參考Use a Migration Manager if Models Cannot Be Found Automatically)。

 

版本遷移過程


那麼,資料移轉的過程是如何進行的?

首先,發生資料移轉需要三個基本條件:可以開啟既有persistent store的sourceModel,新的資料模型destinationModel,以及這兩者之間的映射關係Mapping Model。

利用這三樣,當調用如下代碼時(addPersistentStore):



Core Data建立了兩個stack(分別為source stack和destination stack,可以參考Core Data stack),然後遍曆Mapping Model裡每個entity的映射關係,做以下三件事情:
     1. 基於source stack,Core Data先擷取現有資料,然後在destination stack裡建立當前entity的執行個體,只填充屬性,不建立關係;
     2. 重新建立entity之間的關係;
     3. 驗證資料的完整性和一致性,然後儲存。

考慮到第二步是重建立立entity之間的關係,那麼應該是在第一步就把所有entity的對象都建立好了,並且保留在記憶體中,為第二步服務(事實上也是如此)。

完成第二步後,所有資料還是維持在記憶體中(可能還有兩份,因為有兩個stack),在完成資料驗證後才真正儲存。

這樣的話,會容易導致記憶體佔用過多,因為Core Data在這個遷移過程中也沒有一種機制清理響應的context。所以在資料量較多時,App可能會遇到在資料移轉過程因為記憶體緊張而被系統幹掉。
針對這種情況,我們可以自訂遷移過程。

 

自訂資料移轉(解決記憶體問題)


自訂資料移轉的過程通暢分為三步:
第一步是判斷是否需要進行資料移轉:



第二步是建立一個Migration Manager對象:



第三步是真正發生資料移轉:



上面三幅圖所展示的代碼在記憶體使用量量上跟lightweight migration也沒什麼區別,無法解決記憶體峰值過高的問題。

雖然Core Data專家Marcus S. Zarra比較傾向堅持使用lightweight migration,不過對於上述記憶體佔用過多的問題,Apple官方推薦使用Multiple Passes來解決。

關於Multiple Passes,官方文檔的說明很簡明扼要,如有需要,可以參考Stackoverflow上的這麼一篇文章。

用我的話往簡單裡說就是對資料模型進行劃分,把一份Mapping Model拆分成多份,然後分成多次遷移,從而降低記憶體峰值。這需要對資料庫進行全盤的考慮(甚至可能需要變更部分設計),然後通過合理的劃分把相關聯的Entity放在一份Mapping Model裡面(因為要建立關聯)。

 

新的問題


採用上述方案來解決資料移轉過程中記憶體峰值的問題,我們仍然需要關注遷移所耗費的時間、記憶體,從而能夠在資料上驗證方案的有效性,並且在使用者互動方面進行一些必要的更改(總不能讓使用者傻傻地在那邊等資料移轉吧)。

雖然可以解決記憶體峰值的問題,但也引進了其它問題。

1. 需要對資料模型進行劃分(以及變更),存在一定的工作量和風險;
2. 需要手工建立多份Mapping Model;
3. 需要手工編寫Multiple Passes遷移代碼;
4. 需要在每個版本變遷中都再次建立新的Mapping Model,且在跨版本遷移過程存在著其它問題;
5. 資料模型版本多起來,就面臨著跨版本遷移的問題,是要為每個曆史版本建立到最新模型的Mapping Model,還是只維護最近兩個版本的Mapping Model(更早的版本通過相鄰版本的Mapping Model依次遷移過來,比較耗時)?
6. 對資料模型重新劃分後,無關的Entity簡單變更也會引起整個store和model的不相容,需要遷移,那麼是否考慮分庫?
7. 這麼大的動作服務的使用者數是很少的(只有少數使用者會遇到,或者是很少),但卻是比較資深的(因為訊息記錄多),疼。。。
8. 這無法解決單個Entity資料量過大的問題,針對這種情境,只能自己手工編碼進行小批量的資料移轉;

CoreData版本遷移

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.