加锁机制

本文将指导您如何使用Kronos的锁功能。

给 select 添加锁

数据库查询需要悲观锁时,在 select 链路上使用 lock(...)。不传参数调用 lock() 时,默认使用 SqlLock.Update()。

update lock

import com.kotlinorm.syntax.statement.SqlLock

val user = User()
    .select()
    .where { it.id == 1 }
    .lock(SqlLock.Update())
    .first()

mysql

SELECT `id`, `name`
FROM `user`
WHERE `user`.`id` = :id
FOR UPDATE

Kronos 会把锁信息记录到 select 任务中,并由当前数据库方言渲染。查询字段、条件和结果方法见 📚查询 和 📚结果方法。

使用共享锁

查询需要共享锁或读锁时,使用 SqlLock.Share()。

share lock

val users = User()
    .select()
    .where { it.status == "ACTIVE" }
    .lock(SqlLock.Share())
    .toList()

共享锁和更新锁都会按当前 SQL 方言渲染。请把锁的使用放在需要锁定读取的事务边界附近。

普通 upsert 可以使用锁

普通 upsert().on { ... } 会先检查是否存在匹配行,再选择 update 或 insert。未启用乐观锁策略时,匹配查询默认使用 SqlLock.Update();需要显式声明锁类型时,使用 .lock(...)。

upsert

User(id = 1, name = "Kronos")
    .upsert { it.name }
    .on { it.id }
    .lock(SqlLock.Update())
    .execute()

冲突字段和更新字段示例见 📚更新插入。

乐观锁属于 mutation 策略

乐观锁通过 @Version 或 Kronos.optimisticLockStrategy 配置。它会在 insert、update、逻辑删除和 upsert 路径中初始化或递增版本字段。

version

data class Product(
    @PrimaryKey(identity = true)
    var id: Int? = null,
    @Version
    var version: Int? = null
) : KPojo

版本字段行为见 📚乐观锁 和 📚通用策略。