基于数据库实现分布式锁

基于数据库实现分布式锁

  • 多个进程/多个线程访问共同组件数据库
  • 通过select…for update 访问同一条数据,for update锁定数据,其他线程只能等待

Select For update语句

该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。

mysql默认是自动提交事务的,将窗口1设置为手动提交事务
在窗口1中执行

select * from product where id = '100100' FOR UPDATE

在这里插入图片描述
在窗口2中执行,由于窗口1中并没有提交事务,行锁还没有释放。所以窗口2上锁失败
在这里插入图片描述
窗口1执行

COMMIT;

此时窗口2可以正常上锁
在这里插入图片描述
代码验证

    @RequestMapping("singleLock")
    @Transactional(rollbackFor = Exception.class)
    public String singleLock() throws Exception {
        log.info("我进入了方法!");
        DistributeLock distributeLock = distributeLockMapper.selectDistributeLock("demo");
        if (distributeLock==null) throw new Exception("分布式锁找不到");
        log.info("我进入了锁!");
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "我已经执行完成!";
    }

数据库查询语句

  <select id="selectDistributeLock" resultType="com.example.distributelock.model.DistributeLock">
    select * from distribute_lock
    where business_code = #{businessCode,jdbcType=VARCHAR}
    for update
  </select>

启动两个jvm(9999和9998)
分别请求localhost:9998/singleLock和localhost:9999/singleLock
9998的请求拿到数据库表中的某一行数据的行锁之后,会休眠20秒,此时9999的请求进来之后,由于行锁没有释放,只能进行等待
localhost:9998/singleLock
在这里插入图片描述
localhost:9999/singleLock
在这里插入图片描述
20s之后,9999会获取锁
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值