MySQL死锁案例分析及避免办法

1. 什么是死锁

  • 死锁就是两个以上线程互相竞争资源导致相互等待的现象
  • 发生死锁有四个条件:互斥、请求与保持条件、不可抢占、循环等待

2. 举个栗子:

  • 环境:MYSQL 8.0+,默认隔离级别RR
  • 表存在主键索引和仅name字段的普通索引

2.1. 栗子一:

  • 事务A将id=1的余额字段减100金额,然后对id=2的余额字段加100金额
  • 在两个操作中间时刻,事务B对id=2的余额减300金额,又对id=1的余额加300

在这里插入图片描述

  • 事务A在执行第二条update语句时,需要等待事务B释放id=2的行锁
  • 事务B在执行第二条update语句时,需要等待事务A释放id=1的行锁
  • 所以就发生了死锁
2.1.1 代码栗子:
    @PutMapping("/dead/lock")
    public BaseResponse deadLock() {
   
   
        CompletableFuture.runAsync(() -> userAccountService.deadLock());
        try {
   
   
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
   
   
            throw new RuntimeException(e);
        }
        userAccountService.mockOtherTransactional();
        return BaseResponse.SUCCESS();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deadLock() {
   
   
        try {
   
   
            UserAccount account = this.getById(1L);
            BigDecimal decimal = account.getAmount().subtract(new BigDecimal("100"));
            this.updateAmountById(account.getId(), decimal);
            TimeUnit.SECONDS.sleep(5);

            UserAccount account2 = this.getById(2L);
            BigDecimal decimal2 = account2.getAmount().add(new BigDecimal("100"));
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值