跳到主要内容

数据迁移实战

问题

App 更新后数据库 Schema 变了,如何安全迁移?

答案

Core Data 迁移

// 1. 轻量级迁移(推荐,自动处理简单变更)
let description = NSPersistentStoreDescription()
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true

// 支持的变更:
// - 新增属性(有默认值)
// - 删除属性
// - 重命名属性(需设置 Renaming ID)
// - 新增 Entity

复杂迁移

// 2. 自定义迁移(需要数据转换时)
// 创建 Mapping Model (.xcmappingmodel)
class UserMigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstances(
forSource sInstance: NSManagedObject,
in mapping: NSEntityMapping,
manager: NSMigrationManager
) throws {
let dest = NSEntityDescription.insertNewObject(
forEntityName: "User",
into: manager.destinationContext
)
// 数据转换:将 fullName 拆为 firstName + lastName
let fullName = sInstance.value(forKey: "fullName") as? String ?? ""
let parts = fullName.split(separator: " ")
dest.setValue(String(parts.first ?? ""), forKey: "firstName")
dest.setValue(String(parts.last ?? ""), forKey: "lastName")
}
}

SwiftData 迁移

// SwiftData 使用 VersionedSchema
enum SchemaV1: VersionedSchema {
static var versionIdentifier: Schema.Version = .init(1, 0, 0)
static var models: [any PersistentModel.Type] = [UserV1.self]
}

enum SchemaV2: VersionedSchema {
static var versionIdentifier: Schema.Version = .init(2, 0, 0)
static var models: [any PersistentModel.Type] = [UserV2.self]
}

let plan = SchemaMigrationPlan(schemas: [SchemaV1.self, SchemaV2.self])

安全策略

策略说明
备份迁移前备份数据库文件
灰度新版本先小范围验证
回退迁移失败时恢复备份
测试用旧版本数据库文件跑迁移单元测试

常见面试问题

Q1: 轻量级迁移失败怎么办?

答案:如果 Schema 变更超出轻量级迁移能力(如属性类型改变),需要创建 Mapping Model 自定义迁移逻辑。或者分两步:v1 → v1.5(兼容中间版本)→ v2。

相关链接