首页 >> 基础教程

mysql乐观锁和悲欢锁

      MySQL中的乐观锁和悲观锁是解决数据库并发访问冲突的两种核心策略,它们在设计理念和实现方式上有显著区别:

一、悲观锁(Pessimistic Locking)

核心理念:假设冲突必然发生,操作数据前先加锁独占资源。
实现方式:通过MySQL的锁机制(如SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE)实现。
适用场景:写操作频繁、冲突概率高的场景(如账户扣款、库存争抢)。

START TRANSACTION;
-- 锁定查询到的行(其他事务无法修改)
SELECT * FROM products WHERE id = 1 FOR UPDATE;
-- 执行业务逻辑(如扣减库存)
UPDATE products SET stock = stock - 1 WHERE id = 1;
COMMIT;

特点

  • 优点:保证强一致性,避免并发冲突。

  • 缺点

    • 加锁增加系统开销,降低并发性能。

    • 可能引发死锁(需事务及时提交/回滚)。

    • 锁粒度控制不当易导致性能问题(如行锁升级为表锁)。

二、乐观锁(Optimistic Locking)

核心理念:假设冲突很少发生,提交操作时再检测冲突。
实现方式:通过版本号(version)或时间戳字段实现无锁并发控制
适用场景:读多写少、冲突概率低的场景(如评论更新、配置修改)。

-- 先查询当前版本号
SELECT stock, version FROM products WHERE id = 1;
-- 执行业务逻辑(内存中计算新值)
-- 更新时校验版本号
UPDATE products 
SET stock = stock - 1, version = version + 1 WHERE id = 1 AND version = 旧版本号;
-- 检查是否更新成功(影响行数 > 0)

特点

  • 优点

    • 无锁设计,并发性能高。

    • 避免死锁风险。

  • 缺点

    • 冲突时需重试或回滚,增加业务逻辑复杂度。

    • 不适用高冲突场景(频繁重试可能降低性能)。

    • 存在ABA问题(可通过递增版本号解决)。

三、关键对比

特性悲观锁乐观锁
冲突假设必然发生很少发生
实现方式内置锁机制(FOR UPDATE版本号/时间戳字段
加锁时机操作前加锁提交时检查
性能影响高开销(锁竞争)低开销(无锁)
适用场景高并发写、强一致性要求低冲突、高并发读
复杂度数据库层控制,业务逻辑简单需业务层处理重试
典型用例库存扣减、金融交易更新用户信息、统计计数


四、如何选择?

  1. 悲观锁适用

    • 事务涉及多表复杂更新。

    • 业务逻辑无法容忍重试(如支付交易)。

    • 冲突频率高(如秒杀场景)。

  2. 乐观锁适用

    • 读操作远多于写操作。

    • 冲突概率低(如CMS内容编辑)。

    • 系统要求高吞吐量(如日志记录)。

      乐观锁以版本检测换性能,悲观锁以提前加锁保安全。根据业务场景的冲突概率、一致性要求及性能需求权衡选择,必要时可组合使用(如读用MVCC、写用悲观锁)。

最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1