关键词

SpringBoot整合MyBatis-Plus乐观锁不生效的问题及解决方法

下面我将详细讲解SpringBoot整合MyBatis-Plus乐观锁不生效的问题及解决方法。

问题描述

在使用SpringBoot整合MyBatis-Plus过程中,我们很容易遇到乐观锁不生效的问题。即在多线程操作同一条记录时,最后一次更新的操作会覆盖之前的更新,导致乐观锁失效。

问题原因

MyBatis-Plus默认使用的是OptimisticLockInterceptor乐观锁插件,它在查询时会把version字段加入到WHERE条件中,然后在更新时会把version加1并更新到数据库。如果更新失败则认为乐观锁失败。

而导致乐观锁失效的原因通常是:多个线程拿到的version值相同,但是最终只有一个线程能成功更新数据库,其他线程都会更新失败。

解决方法

1. 使用数据中心统一生成version值

在多个应用中如果使用自增长字段作为version,那么同一个行被多次更新时由于同一个JVM程序中的多个线程更新该行,version值每次加1 可能重复。而利用统一的发号器生成 version 值则能确保这种情况不会发生。

示例代码:

public class VersionGenerator {
    private static final SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(1, 1);
    public static Long nextId() {
        return snowflakeIdWorker.nextId();
    }
}

2. 使用数据库层面的乐观锁

在MySQL数据库中,可以使用update t_order set name = #{name},price = #{price},version = version + 1 where id = #{id} and version = #{version}语句实现乐观锁。如果更新失败则代表乐观锁失效。

示例代码:

public void updateOrder(Order order) {
    String sql = "update t_order set name = ?, price = ?, version = version + 1 where id = ? and version = ?";
    Object[] args = new Object[]{order.getName(), order.getPrice(), order.getId(), order.getVersion()};
    int count = jdbcTemplate.update(sql, args);
    if (count != 1) {
        throw new RuntimeException("Update Failed, order:" + order);
    }
}

总结

SpringBoot整合MyBatis-Plus乐观锁不生效的问题,通常是由于多线程操作同一记录导致的。可以通过使用数据中心统一生成version值或者使用数据库层面的乐观锁的方法解决该问题。

本文链接:http://task.lmcjl.com/news/13995.html

展开阅读全文