MySQL乐观锁和悲观锁的使用与区别

 更新时间:2026年03月24日 10:50:11   作者:晚夜微雨问海棠呀  
MySQL中的乐观锁和悲观锁是两种并发控制策略,本文就来详细的介绍一下MySQL乐观锁和悲观锁的使用与区别,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

MySQL 中的乐观锁和悲观锁是两种不同的并发控制策略,它们各有特点和适用场景。

一、悲观锁(Pessimistic Locking)

概念

悲观锁假设数据冲突经常发生,因此在操作数据之前先获取锁,确保在事务期间数据不会被其他事务修改。

实现方式

使用数据库内置的锁机制:

-- 1. 开始事务
START TRANSACTION;

-- 2. 加排他锁(悲观锁)
SELECT * FROM products WHERE id = 1 FOR UPDATE;

-- 3. 执行业务逻辑
UPDATE products SET stock = stock - 1 WHERE id = 1;

-- 4. 提交事务
COMMIT;

特点

  • 思想:先加锁,后操作
  • 实现:依赖数据库锁机制(行锁、表锁等)
  • 适用场景
    • 写操作频繁的场景
    • 数据竞争激烈的环境
    • 需要强一致性的业务

优缺点

优点

  • 保证强一致性
  • 实现简单,直接使用数据库功能
  • 适合高并发写场景

缺点

  • 性能开销大(加锁、释放锁)
  • 可能产生死锁
  • 降低系统并发度

二、乐观锁(Optimistic Locking)

概念

乐观锁假设数据冲突很少发生,因此不加锁直接操作,只在提交时检查数据是否被修改过。

实现方式

通常使用版本号或时间戳:

方法1:版本号机制

-- 表结构增加版本字段
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    stock INT,
    version INT DEFAULT 0
);

-- 更新时检查版本号
UPDATE products 
SET stock = stock - 1, version = version + 1 
WHERE id = 1 AND version = 1;  -- 这里的1是读取时的版本号

-- 检查影响行数,如果为0表示版本不一致,需要重试

方法2:时间戳机制

-- 表结构增加时间戳字段
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    stock INT,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 更新时检查时间戳
UPDATE products 
SET stock = stock - 1 
WHERE id = 1 AND update_time = '2024-01-01 10:00:00';

方法3:条件判断(基于业务字段)

-- 基于库存数量判断
UPDATE products 
SET stock = stock - 1 
WHERE id = 1 AND stock > 0;

重试机制

由于乐观锁可能失败,通常需要配合重试逻辑:

// Java 示例代码
public boolean deductStockWithRetry(int productId, int quantity) {
    for (int i = 0; i < MAX_RETRY; i++) {
        Product product = productDao.getById(productId);
        if (product.getStock() < quantity) {
            return false; // 库存不足
        }
        int affectedRows = productDao.updateStock(productId, quantity, product.getVersion());
        if (affectedRows > 0) {
            return true; // 更新成功
        }
        // 版本冲突,重试
        Thread.sleep(100); // 短暂等待
    }
    throw new RuntimeException("更新失败,超过最大重试次数");
}

特点

  • 思想:先操作,提交时检查
  • 实现:基于应用层逻辑(版本号、时间戳等)
  • 适用场景
    • 读多写少的场景
    • 数据冲突较少的业务
    • 对性能要求高的系统

优缺点

优点

  • 提高系统并发性能
  • 避免死锁问题
  • 减少数据库锁开销

缺点

  • 实现相对复杂
  • 需要处理更新失败的情况
  • 不适合高并发写场景

三、对比总结

特性悲观锁乐观锁
思想先加锁后操作先操作后检查
实现方式数据库锁机制版本号/时间戳
性能并发度低,开销大并发度高,开销小
适用场景写多读少,冲突频繁读多写少,冲突较少
一致性强一致性最终一致性
死锁风险
实现复杂度简单相对复杂

四、实际应用建议

选择悲观锁的场景

  • 银行转账、库存扣减等金融业务
  • 需要强一致性的核心业务
  • 写操作非常频繁的系统

选择乐观锁的场景

  • 商品浏览、社交媒体的点赞功能
  • 读多写少的业务系统
  • 对性能要求较高的互联网应用

混合使用策略

在实际项目中,可以根据不同业务场景混合使用:

-- 核心业务使用悲观锁
START TRANSACTION;
SELECT * FROM account WHERE user_id = 123 FOR UPDATE;
-- 执行资金操作
COMMIT;
-- 非核心业务使用乐观锁
UPDATE article SET like_count = like_count + 1 
WHERE id = 456 AND version = current_version;

五、注意事项

  1. 悲观锁要合理设置事务隔离级别和锁等待超时时间
  2. 乐观锁要设计合理的重试策略和重试次数上限
  3. 在高并发场景下,乐观锁的重试可能造成"惊群效应"
  4. 根据业务特点选择合适的锁策略,不要一概而论

这两种锁策略各有优劣,关键在于根据具体的业务场景和性能要求来选择最合适的方案。

到此这篇关于MySQL乐观锁和悲观锁的使用的文章就介绍到这了,更多相关MySQL乐观锁和悲观锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL数据库约束深入详解

    MySQL数据库约束深入详解

    这篇文章主要介绍了MySQL数据库约束,在MySQL数据库中,约束是用来限制进入表中的数据类型的一种技术,通过使用约束,可以确保数据的准确性、完整性和可靠性,需要的朋友可以参考下
    2025-05-05
  • MySQL复合查询的具体使用

    MySQL复合查询的具体使用

    本文介绍了MySQL复合查询的基本操作,包括多表查询和复杂条件查询,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • Mysql数据库锁定机制详细介绍

    Mysql数据库锁定机制详细介绍

    这篇文章主要介绍了Mysql数据库锁定机制详细介绍,本文用大量内容讲解了Mysql中的锁定机制,例如MySQL锁定机制简介、合理利用锁机制优化MySQL等内容,需要的朋友可以参考下
    2014-12-12
  • 查看本地MYSQL数据库IP地址的三种方法

    查看本地MYSQL数据库IP地址的三种方法

    本文介绍了多种方法来查看连接到本地MySQL服务器的IP地址,括使用SQL查询从`information_schema.processlist`获取IP地址,并通过`group by`进行统计,以及通过命令行工具如`mysql`和`awk`进行过滤和计数,这些方法有助于监控和管理数据库连接,需要的朋友可以参考下
    2024-10-10
  • MySQL解压版配置步骤详细教程

    MySQL解压版配置步骤详细教程

    这篇文章主要介绍了MySQL解压版配置步骤详细教程的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-12-12
  • Ubuntu18.04 安装mysql8.0.11的图文教程

    Ubuntu18.04 安装mysql8.0.11的图文教程

    本文通过图文并茂的形式给大家介绍了Ubuntu18.04 安装mysql8.0.11的方法,非常不错,具有一定的参考借鉴价值,需要的的朋友参考下吧
    2018-07-07
  • MySQL的执行原理之 MySQL的查询重写规则详解

    MySQL的执行原理之 MySQL的查询重写规则详解

    MySQL 性能调优是一个复杂且多维度的过程,下面从数据库设计、查询优化、配置参数调整、硬件优化几个方面为你介绍相关的调优方法,本文给大家介绍MySQL的执行原理之 MySQL的查询重写规则,感兴趣的朋友一起看看吧
    2025-04-04
  • MySQL 根据表名称生成完整select语句详情

    MySQL 根据表名称生成完整select语句详情

    这篇文章主要介绍了MySQL 根据表名称生成完整select语句,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • 一文带你深入了解 MySQL的锁机制

    一文带你深入了解 MySQL的锁机制

    在数据库系统中,同时有多个用户或进程访问数据是常见的情况,为了确保数据的完整性和一致性,数据库管理系统引入了锁机制,本文将深入探讨 MySQL 锁机制,帮助您理解锁的分类、实现方式以及使用场景和优化策略,需要的朋友可以参考下
    2023-05-05
  • JDBC连接的六步实例代码(与mysql连接)

    JDBC连接的六步实例代码(与mysql连接)

    这篇文章主要给大家介绍了关于JDBC连接的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05

最新评论