在读写比例场景下,如何抉择MySQL悲观锁与乐观锁以优化性能压测?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1132个文字,预计阅读时间需要5分钟。
MySQL中的`SELECT ... FOR UPDATE`是经典的悲观锁实现方式,它会在事务中对选中的行加写锁,直到事务提交或回滚。这在多读少写、操作频繁争夺同一行数据的情况下风险较大——比如数据库库存扣减、账户余额更新等。压测时常见的问题是大量线程在等待表元数据锁,或者直接报错Lock wait timeout exceeded。
实操建议:
- 仅在明确知道冲突概率高、且业务能接受串行化写入时使用,例如金融类强一致性转账
- 务必确保
SELECT ... FOR UPDATE语句命中索引,否则会升级为表锁,压测 QPS 可能断崖式下跌 - 事务粒度要小:避免在锁住行后执行 HTTP 调用、日志写入等耗时操作
- 设置合理
innodb_lock_wait_timeout(默认 50 秒),并捕获Deadlock found when trying to get lock错误做重试
乐观锁更适合读多写少 + 冲突概率低的业务场景
乐观锁本质是“先查后验”,典型做法是在表中加 version 字段或用 UPDATE ... WHERE version = ? AND id = ? 做条件更新。压测数据显示,在读写比 > 9:1 的场景(如商品详情页浏览+少量收藏/加购),乐观锁吞吐量通常比悲观锁高 3–5 倍,因为无锁开销、无等待队列。
本文共计1132个文字,预计阅读时间需要5分钟。
MySQL中的`SELECT ... FOR UPDATE`是经典的悲观锁实现方式,它会在事务中对选中的行加写锁,直到事务提交或回滚。这在多读少写、操作频繁争夺同一行数据的情况下风险较大——比如数据库库存扣减、账户余额更新等。压测时常见的问题是大量线程在等待表元数据锁,或者直接报错Lock wait timeout exceeded。
实操建议:
- 仅在明确知道冲突概率高、且业务能接受串行化写入时使用,例如金融类强一致性转账
- 务必确保
SELECT ... FOR UPDATE语句命中索引,否则会升级为表锁,压测 QPS 可能断崖式下跌 - 事务粒度要小:避免在锁住行后执行 HTTP 调用、日志写入等耗时操作
- 设置合理
innodb_lock_wait_timeout(默认 50 秒),并捕获Deadlock found when trying to get lock错误做重试
乐观锁更适合读多写少 + 冲突概率低的业务场景
乐观锁本质是“先查后验”,典型做法是在表中加 version 字段或用 UPDATE ... WHERE version = ? AND id = ? 做条件更新。压测数据显示,在读写比 > 9:1 的场景(如商品详情页浏览+少量收藏/加购),乐观锁吞吐量通常比悲观锁高 3–5 倍,因为无锁开销、无等待队列。

