在MySQL高并发场景中,如何选择悲观锁或乐观锁以优化并发控制?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1243个文字,预计阅读时间需要5分钟。
确保在进行读取、业务判断和更新操作时保持原子性,使用`SELECT ... FOR UPDATE`语句才有意义。例如,库存减少:
常见错误现象:Deadlock found when trying to get lock 或响应明显变慢,往往是因为锁范围过大(比如没走索引导致锁全表),或事务里混了非数据库操作(如调外部 API、sleep)让锁持有太久。
- 必须确保
FOR UPDATE的查询条件命中索引,否则升级为表级锁; - 事务越短越好,查完立刻更新,别在事务里做日志打印、HTTP 请求这类耗时操作;
- InnoDB 下,
FOR UPDATE只对当前读生效,快照读(普通SELECT)仍可见旧值,这点常被忽略。
version 字段做乐观锁,为什么不能只靠 WHERE version = ?
只加 WHERE version = ? 是乐观锁的必要条件,但不是充分条件。真正起作用的是:每次更新后必须同步递增 version,且应用层要检查 UPDATE 影响行数是否为 1。如果影响行为 0,说明已被别人抢先改过,当前操作应失败重试或提示冲突。
容易踩的坑:version 字段类型用 INT 没问题,但千万别用 TIMESTAMP 或 datetime——并发下毫秒级重复、时钟回拨都会导致校验失效。
本文共计1243个文字,预计阅读时间需要5分钟。
确保在进行读取、业务判断和更新操作时保持原子性,使用`SELECT ... FOR UPDATE`语句才有意义。例如,库存减少:
常见错误现象:Deadlock found when trying to get lock 或响应明显变慢,往往是因为锁范围过大(比如没走索引导致锁全表),或事务里混了非数据库操作(如调外部 API、sleep)让锁持有太久。
- 必须确保
FOR UPDATE的查询条件命中索引,否则升级为表级锁; - 事务越短越好,查完立刻更新,别在事务里做日志打印、HTTP 请求这类耗时操作;
- InnoDB 下,
FOR UPDATE只对当前读生效,快照读(普通SELECT)仍可见旧值,这点常被忽略。
version 字段做乐观锁,为什么不能只靠 WHERE version = ?
只加 WHERE version = ? 是乐观锁的必要条件,但不是充分条件。真正起作用的是:每次更新后必须同步递增 version,且应用层要检查 UPDATE 影响行数是否为 1。如果影响行为 0,说明已被别人抢先改过,当前操作应失败重试或提示冲突。
容易踩的坑:version 字段类型用 INT 没问题,但千万别用 TIMESTAMP 或 datetime——并发下毫秒级重复、时钟回拨都会导致校验失效。

