mybatis实现基于数据库的乐观锁

在更新冲突概率低的场景,乐观锁比悲观锁性能更高。

本文讲一下mybatis的乐观锁实现,我们的测试表如下:

要做的事情是获取status为1的一条数据,并更新status状态为2。 在并发情况下,用事务或者将查询更新两个操作加锁执行效率都不是很高。

我们更希望用乐观锁解决并发问题。

一开始我的代码是这样写的:

        Stock stock = mapper.findOneByStatus();
        //do something
        int affectedRows = 0;
        do {
            //这里我们希望返回的是MySQL执行时的影响行数
            affectedRows = mapper.update(stock);
        } while (affectedRows == 0);

update对应SQL如下:

<update id="update">
        UPDATE
            stock
        SET status = 2
        WHERE id = #{id}
 </update>

压测时,发现update返回的影响行数始终是1,不符合预期,高并发下,应该会有很多结果返回是0的。

通过查资料,发现原来mybatis的update返回的并不是影响行数,而是matched的行数

因为每次通过id去update,所以每次matched为1,返回1。

踩坑后,决定添加version字段,利用version,基于matched来实现乐观锁。如下:

        Stock stock = mapper.findOneByStatus();
        //do something
        int matchedRows = 0;
        do {
            matchedRows = mapper.update(stock);
        } while (matchedRows == 0);

mapper的update

   <update id="update">
        UPDATE
            stock
        SET status = 2,version = version +1
<!-- version是否相等决定返回值matched是0还是1 -->
        WHERE id = #{id} and version = ${version}
    </update>

 

经过压测,上述通过version实现的乐观锁,很好的解决了并发的问题。

# java 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×