Swift 中使用 SQLite——批量更新(事务处理)

本文是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)")
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章