乐观锁是一种基于版本号的并发控制机制,它假设并发访问的数据冲突的概率很小,因此不会阻塞线程,而是在更新数据时检查数据版本号是否一致,如果一致则更新数据,如果不一致则放弃更新并抛出异常或者重试。

在MySQL中,可以使用版本号字段实现乐观锁。假设我们有一张user表,其中包含id、name和version三个字段。现在要更新id为1的用户的name字段,可以如下实现:

START TRANSACTION;

SELECT version FROM user WHERE id = 1;

UPDATE user SET name = 'new_name', version = version + 1 WHERE id = 1 AND version = ?;

COMMIT;

其中,第一条SELECT语句获取当前用户的版本号,第二条UPDATE语句更新用户的name字段,并将版本号加1。如果UPDATE语句受影响的行数为0,说明版本号不匹配,更新失败,可以抛出异常或者重试。如果UPDATE语句受影响的行数为1,说明更新成功。

完整的乐观锁示例代码如下:

public void updateUser(String name, long id) throws SQLException {
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        conn = getConnection();
        conn.setAutoCommit(false);
        // 获取当前用户的版本号
        pstmt = conn.prepareStatement("SELECT version FROM user WHERE id = ?");
        pstmt.setLong(1, id);
        rs = pstmt.executeQuery();
        if (rs.next()) {
            long version = rs.getLong("version");
            // 更新用户的name字段,并将版本号加1
            pstmt = conn.prepareStatement("UPDATE user SET name = ?, version = ? WHERE id = ? AND version = ?");
            pstmt.setString(1, name);
            pstmt.setLong(2, version + 1);
            pstmt.setLong(3, id);
            pstmt.setLong(4, version);
            int rows = pstmt.executeUpdate();
            if (rows == 1) {
                // 更新成功,提交事务
                conn.commit();
            } else {
                // 更新失败,回滚事务
                conn.rollback();
                throw new SQLException("Update failed due to version mismatch.");
            }
        } else {
            throw new SQLException("User not found.");
        }
    } catch (SQLException e) {
        if (conn != null) {
            conn.rollback();
        }
        throw e;
    } finally {
        closeResources(conn, pstmt, rs);
    }
}
用mysql实现一段乐观锁代码

原文地址: https://www.cveoy.top/t/topic/s9w 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录