本文是Swift 中使用 SQLite系列的收官之作,介绍一下在数据库中的批量更新。
事务
- 在准备做
大规模数据操作前
,首先开启一个事务,保存操作前的数据库的状态 - 开始数据操作
- 如果数据操作成功,
提交
事务,让数据库更新到数据操作后的状态 - 如果数据操作失败,
回滚
事务,让数据库还原到操作前的状态
准备事务代码
// MARK: - 事务处理
/// 开启事务
func beginTransaction() {sqlite3_exec(db, "BEGIN TRANSACTION;", nil, nil, nil)
}/// 提交事务
func commitTransaction() {sqlite3_exec(db, "COMMIT TRANSACTION;", nil, nil, nil)
}/// 回滚事务
func rollbackTransaction() {sqlite3_exec(db, "ROLLBACK TRANSACTION;", nil, nil, nil)
}
用事务插入大量数据
- 不使用事务插入数据
/// 不使用事务插入多条记录 - 测试记录 5s
private func manyPerson1() {print("start")let start = CACurrentMediaTime()for i in 0..<10000 {Person(dict: ["name": "zhang - \(i)", "age": 18, "height": 1.7]).insertPerson()}print("over \(CACurrentMediaTime() - start)")
}
- 使用事务插入数据
/// 使用事务插入多条数据 - 测试记录 0.4s
private func manyPerson2() {print("start")let start = CACurrentMediaTime()SQLiteManager.sharedManager.execSQL("BEGIN TRANSACTION;")for i in 0..<10000 {Person(dict: ["name": "zhang - \(i)", "age": 18, "height": 1.7]).insertPerson()}SQLiteManager.sharedManager.execSQL("COMMIT TRANSACTION;")print("over \(CACurrentMediaTime() - start)")
}
原因:在 SQLite 中,如果不主动开启事务,每个数据更新操作 (INSERT / UPDATE / DELETE) 都会默认开启一个事务,数据更新结束后自动提交事务
- 模拟失败
/// 模拟失败
private func manyPerson3() {print("start")let start = CACurrentMediaTime()SQLiteManager.sharedManager.execSQL("BEGIN TRANSACTION;")for i in 0..<10000 {Person(dict: ["name": "zhang - \(i)", "age": 18, "height": 1.7]).insertPerson()if i == 1000 {SQLiteManager.sharedManager.execSQL("ROLLBACK TRANSACTION;")// 注意:一定要使用 break 退出循环break;}}SQLiteManager.sharedManager.execSQL("COMMIT TRANSACTION;")print("over \(CACurrentMediaTime() - start)")
}
- 标准写法
/// 标准写法
private func manyPerson4() {print("start")let start = CACurrentMediaTime()SQLiteManager.sharedManager.execSQL("BEGIN TRANSACTION;")for i in 0..<10000 {if !Person(dict: ["name": "zhang - \(i)", "age": 18, "height": 1.7]).insertPerson() {SQLiteManager.sharedManager.execSQL("ROLLBACK TRANSACTION;")break;}}SQLiteManager.sharedManager.execSQL("COMMIT TRANSACTION;")print("over \(CACurrentMediaTime() - start)")
}