开发者

MySQL中的乐观锁和悲观锁的区别及说明

目录
  • 1. 悲观锁(Pessimistic Locking)
    • 核心思想
    • 实现方式
    • 适用场景
    • 示例
  • 2. 乐观锁(Optimistic Locking)
    • 核心思想
    • 实现方式
    • 适用场景
    • 示例
  • 3. 对比总结
    • 4. mysql 中的实际选择
      • 总结

        在 MySQL 中,乐观锁悲观锁是两种不同的并发控制机制,用于解决多用户/事务同时操作数据时的冲突问题。

        它们的核心理念和实现方式有显著区别:

        1. 悲观锁(Pessimistic Locking)

        核心思想

        假设数据会被频繁修改,因此提前对数据进行加锁,防止其他事务访问,直到当前事务完成操作并释放锁。

        实现方式

        php

        显式加锁:通过 SQL 语句主动申请锁。

        • 排他锁(X Lock)
        SELECT ... FOR UPDATE

        (在事务中锁定选中的行,阻止其他事务修改或加锁)

        • 共享锁(S Lock)
        SELECT ... LOCK IN SHARE MODE

        (允许其他事务读,但阻止写操作)

        隐式加锁:数据库自动管理(如 MySQL 的 InnoDB 引擎默认使用行级锁)。

        适用场景

        • 写多读少的场景(如频繁更新的数据)。
        • 需要强一致性且冲突概率较高时(如金融交易)。

        示例

        START TRANSACTION;
        -- 锁定用户账户余额(排他锁)
        SELECT balance FROM accounts WHERE user_id = 1 FOR UPDATE;
        -- 执行扣款操作
        UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
        COMMIT;

        优点:

        • 保证数据操作的原子性和一致性。
        • 适合高竞争场景(冲突概率高时效率更高)。

        缺点:

        • 可能导致死锁(需应用层处理)。
        • 降低并发性能(长时间持有锁会阻塞其他操作)。

        2. 乐观锁(Optimistic Locking)

        核心思想

        假设数据冲突较少发生,因此不加锁,而是在更新时检查数据是否被修改过。若被修改过,则编程拒绝操作或重试。

        实现方式

        • 版本号(Version):在表中增加 version 字段,更新时验证版本号。
        UPDATE table 
        SET 
          column = new_value, 
          version = version + 1 
        WHERE 
          id = 1 AND version = old_version;
        • 时间戳(Timestamp):类似版本号,但使用时间戳标记数据修改时间。
        • CAS(Compare-And-Swap):在应用层比较数据一致cVlpRvI性后再提交。

        适用场景

        • 读多写少的场景(如商品库存充足时的秒杀)。
        • 冲突概率较低时(如用户点赞操作)。

        示例

        -- 初始查询(获取当前版本号)
        SELECT balance, version FROM accounts WHERE user_id = 1;
        
        -- 更新时检查版本号
        UPDATE accounts 
        SET 
          balance = balance - 100, 
          version = version + 1 
        WHERE 
          user_id = 1 AND version = 1; -- 假设旧版本号是1
        
        -- 如果受影响行数=0,说明版本已过期,需重试或报错

        优点:

        • 无锁竞争,并发性能高。
        • 避免死锁问题。

        缺点:

        • 冲突发生时需处理重试逻辑(如循环重试或返回错误)。
        • 无法保证强一致性(最终一致性)。

        3. 对比总结

        特性悲观锁乐观锁
        加锁时机操作前加锁操作后验证
        实现复杂度依赖数据库机制需应用层配合(如版本号)
        并发性能较低(锁竞争)较高(无锁)
        适用场景高竞争、强一致性低竞争、最终android一致性
        典型问题死锁、性能瓶颈版本冲突、重试逻辑

        4. MySQL 中的实际选择

        • InnoDB 引擎:支持行级锁,适合悲观锁(需显式使用 FOR UPDATE)。
        • MyISAM 引擎:仅支持表级锁,悲观锁性能较差,通常不推荐。
        • 乐观锁:需在应用层实现(如通过版本号字段),与存储引擎无关。

        根据业务场景选择:

        • 金融交易等强一致性android场景 → 悲观锁
        • 高并发读多写少场景 → 乐观锁

        总结

        以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新数据库

        数据库排行榜