【面试题精讲】Mysql如何实现乐观锁

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

首发博客地址

文章更新计划

系列文章地址


在 MySQL 中,可以通过使用乐观锁来实现并发控制,以避免数据冲突和并发更新问题。乐观锁是一种乐观的思想,它假设并发操作不会导致冲突,只有在提交更新时才会检查是否发生冲突。

下面介绍两种常见的实现乐观锁的方式:

  1. 版本号(Version)机制:

    • 在数据表中添加一个版本号字段,通常是一个整数类型。
    • 当读取数据时,将版本号一同读取出来。
    • 在更新数据时,先检查当前读取的版本号是否与数据库中的版本号一致,如果一致则进行更新操作,并将版本号加 1;如果不一致,则表示数据已经被其他事务修改,需要进行相应的处理(例如回滚或者重新尝试)。
    • 通过版本号的比较,可以判断数据是否被其他事务修改过,从而实现乐观锁的效果。

    示例代码如下(使用 Java 语言):

    java 复制代码
    // 读取数据
    String sql = "SELECT id, name, version FROM table_name WHERE id = ?";
    PreparedStatement pstmt = connection.prepareStatement(sql);
    pstmt.setInt(1, id);
    ResultSet rs = pstmt.executeQuery();
    if (rs.next()) {
        int version = rs.getInt("version");
        // 更新数据
        String updateSql = "UPDATE table_name SET name = ?, version = ? WHERE id = ? AND version = ?";
        PreparedStatement updateStmt = connection.prepareStatement(updateSql);
        updateStmt.setString(1, newName);
        updateStmt.setInt(2, version + 1);
        updateStmt.setInt(3, id);
        updateStmt.setInt(4, version);
        int affectedRows = updateStmt.executeUpdate();
        if (affectedRows == 0) {
            // 更新失败,数据已被其他事务修改
            // 进行相应的处理
        }
    }
  2. 时间戳(Timestamp)机制:

    • 在数据表中添加一个时间戳字段,通常是一个时间类型(如 DATETIME 或 TIMESTAMP)。
    • 当读取数据时,将时间戳一同读取出来。
    • 在更新数据时,先检查当前读取的时间戳是否与数据库中的时间戳一致,如果一致则进行更新操作;如果不一致,则表示数据已经被其他事务修改,需要进行相应的处理。
    • 通过时间戳的比较,可以判断数据是否被其他事务修改过,从而实现乐观锁的效果。

    示例代码如下(使用 Java 语言):

    java 复制代码
    // 读取数据
    String sql = "SELECT id, name, timestamp FROM table_name WHERE id = ?";
    PreparedStatement pstmt = connection.prepareStatement(sql);
    pstmt.setInt(1, id);
    ResultSet rs = pstmt.executeQuery();
    if (rs.next()) {
        Timestamp timestamp = rs.getTimestamp("timestamp");
        // 更新数据
        String updateSql = "UPDATE table_name SET name = ?, timestamp = ? WHERE id = ? AND timestamp = ?";
        PreparedStatement updateStmt = connection.prepareStatement(updateSql);
        updateStmt.setString(1, newName);
        updateStmt.setTimestamp(2, newTimestamp);
        updateStmt.setInt(3, id);
        updateStmt.setTimestamp(4, timestamp);
        int affectedRows = updateStmt.executeUpdate();
        if (affectedRows == 0) {
            // 更新失败,数据已被其他事务修改
            // 进行相应的处理
        }
    }

需要注意的是,乐观锁并不能完全解决并发冲突的问题,它只是一种减少冲突概率的机制。在使用乐观锁时,需要注意处理并发冲突的情况,例如通过重试机制或者回滚操作来处理更新失败的情况。此外,乐观锁适用于并发读多写少的场景,如果并发写操作较多,可能会导致大量的重试和回滚操作,影响性能。

本文由mdnice多平台发布

相关推荐
凌览几秒前
2026年1月编程语言排行榜|C#拿下年度语言,Python稳居第一
前端·后端·程序员
码事漫谈2 分钟前
【深度解析】为什么C++有了malloc,还需要new?
后端
晴虹10 分钟前
lecen:一个更好的开源可视化系统搭建项目--组件和功能按钮的权限控制--全低代码|所见即所得|利用可视化设计器构建你的应用系统-做一
前端·后端·低代码
Java编程爱好者11 分钟前
Java 并发编程:JUC 包中原子操作类的原理和用法
后端
爱分享的鱼鱼12 分钟前
Pinia 深度解析:现代Vue应用状态管理最佳实践
前端·后端
JOEH6013 分钟前
🚀 别再用 Future.get() 傻等了!CompletableFuture 异步编排实战,性能提升 300%!
后端·程序员
神奇小汤圆17 分钟前
原来可以搭建一个HTTP服务
后端
Hooray1117 分钟前
前后端分离_案例学习_Python+Flask+VUE3
后端·python·学习·flask
计算机毕设VX:Fegn089519 分钟前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
计算机毕设VX:Fegn089523 分钟前
计算机毕业设计|基于springboot + vue博物馆展览与服务一体化系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计