mysql乐观锁重试_乐观锁加重试,并发更新数据库一条记录导致:Lock wait timeout exceeded...

背景:

mysql数据库,用户余额表有一个version(版本号)字段,作为乐观锁。

更新方法有事务控制:

@Transactional(rollbackFor = Exception.class)

更新时,比对版本号,如果版本号不一致,则更新失败。

有重试机制,如果更新失败,则查询最新版本号,再次更新,重试超过5次,报错退出。

更新的核心方法:

public boolean updateUserAccount(Long userId, int amount) {

boolean retryable;

int attemptNumber = 0;

do {

// 查询最新版本号

UserAccount userAccount = accountMapper.selectByPrimaryKey(userId);

long oldVersion = userAccount.getVersion();

// 更新

boolean success = accountMapper.updateBalance(amount, new Date(), userId, oldVersion) > 0;

if (success) {

return true;

} else {

attemptNumber++;

retryable = attemptNumber < 5;

if (attemptNumber == 5) {

log.error("超过最大重试次数");

break;

}

try {

Thread.sleep(300);

} catch (InterruptedException e) {

log.error(e);

}

}

} while (retryable);

return false;

}

更新语句:

UPDATE user_account

SET

balance = balance - #{amount,jdbcType=INTEGER},

update_time = #{updateTime,jdbcType=TIMESTAMP},

version = #{version,jdbcType=BIGINT} + 1

WHERE balance > #{amount,jdbcType=INTEGER}

AND user_id = #{userId,jdbcType=BIGINT}

AND version = #{version,jdbcType=BIGINT};

在并发更新时,报异常:Lock wait timeout exceeded

分析:

根据日志分析出:

线程a、b几乎同时到达

线程a查询版本号:856

线程a更新数据库:成功

数据库当前版本号:857

线程b查询到的版本号:856(实际已不是最新)

线程b更新数据库:失败

线程b重试,查询版本号:856

线程b更新数据库:失败

。。。

线程b超过重试次数,退出

线程b重试的过程中,又有其他线程到来,比如c,d,e

线程c查询版本号:857

线程c更新数据库:阻塞,因为b拿到锁一直在重试

线程d查询版本号:857

线程d更新数据库:阻塞,因为b拿到锁一直在重试

线程b超次数退出后,c,d,e争抢锁

d拿到锁,更新数据库:成功

数据库当前版本号:858

线程c查询到的版本号:857(实际已不是最新)

线程c更新数据库:失败

线程c重试,查询版本号:857

线程c更新数据库:失败

。。。

线程c超过重试次数,退出

重试次数过多,事务执行时间超过mysql默认的锁等待时间(50s),就会报出:Lock wait timeout exceeded

为什么线程读不到最新的版本号呢?原来是用到了事务,且mysql默认事务隔离级别Repeatable Read,把隔离级别改为READ_COMMITTED,问题解决:

@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)

分析了这么多,解决问题其实只需要一行代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql集群需要几个ip_rac集群3组机器,scan到底需要几个IP?

这是scan ip的解析&#xff0c; scan ip 最多可以设置3个&#xff0c;最少是一个&#xff0c;不管有几个nodehttp://docs.oracle.com/cd/E11882 ... ncepts.htm#BABHEIBDD.1.3.5 About the SCANOracle Database 11g release 2 clients connect to the database using SCANs. Th…

信息管理系统 github_Java+MySQL实现学生信息管理系统

基于Java swingMySQL实现学生信息管理系统&#xff1a;主要实现JDBC对学生信息进行增删改查&#xff0c;应付一般课设足矣&#xff0c;分享给大家。源码&#xff1a;https://github.com/ZhuangM/student.git1、 开发环境&#xff1a;jdk7MySQL5win7代码结构&#xff1a;model-d…

smith标准型_线性系统理论(八)多项式矩阵Smith-McMillan标准型计算方法

1 参考[1]Chenglin Li&#xff1a;线性系统理论&#xff08;七&#xff09;finite- and infinite-zeros​zhuanlan.zhihu.com多项式矩阵Smith-McMillan标准型确定方法分析2 单模矩阵法Chenglin Li&#xff1a;线性系统理论&#xff08;七&#xff09;finite- and infinite-zero…

Python学习笔记(二) 数据类型及相关函数

本文主要介绍了python中注释方法、变量定义规则、数据类型及相关函数的内容 注释 注释方法&#xff1a; “”“ ”“” ’’’ ‘’’ 解释器位置特殊注释&#xff1a; #!/usr/bin/python3 #coding:utf-8 指定编码格式 #--coding:utf8-- 变量名称定义规则 python变量名称…

mysql explain insert_简述Mysql Explain 命令

MySQL的EXPLAIN命令用于SQL语句的查询执行计划(QEP)。这条命令的输出结果能够让我们了解MySQL 优化器是如何执行SQL语句的。这条命令并没有提供任何调整建议&#xff0c;但它能够提供重要的信息帮助你做出调优决策。参考官方文档地址:为什么用explain . 如果你的页面返回结果很…

没有varselect这个函数_C++的虚函数,虚析构函数,纯虚函数

修改日期&#xff1a;2020/9/6C的虚函数C的虚函数的特点就是动态绑定&#xff0c;它的意思是动态绑定&#xff0c;在运行的时候&#xff0c;通过引用和指针&#xff0c;可以用基类的类&#xff0c;引用继承该c类的派生类&#xff0c;虽然指针是基类&#xff0c;但实际上运行的是…

mysql数据库初识实训总结_MySQL(数据库)的初识

1.什么是数据库数据库(Database)是按照数据结构来组织、存储和管理数据的仓库2.什么是MySQLMySQL 是最流行的关系型数据库管理系统&#xff0c;在WEB应用方面 MySQL 是最好的RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。3.关系数…

jdk1.8要安装什么mysql_Window下安装JDK1.8+Tomcat9.0.27+Mysql5.7.28的教程图解

JDK1.8安装下载打开链接: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html.下拉选择不同jdk版本&#xff0c;图示为window系统下载提示需登录账号可查看这个帖子Oracle账号.安装双击下载的安装包&#xff0c;按提示走就可以安装完成之后…

mysql 实例启动利用binlog恢复_mysql利用binlog进行数据恢复

mysql利用binlog进行数据恢复最近线上误操作了一个数据&#xff0c;由于是直接修改的数据库&#xff0c;所有唯一的恢复方式就在mysql的binlog。binlog使用的是ROW模式&#xff0c;即受影响的每条记录都会生成一个sql。同时利用了binlog基本配置和格式binlog基本配置binlog需要…

php mysql bootstart_PHP MySQL 创建数据库

PHP MySQL 创建数据库数据库存有一个或多个表。你需要 CREATE 权限来创建或删除 MySQL 数据库。使用 MySQLi 和 PDO 创建 MySQL 数据库CREATE DATABASE 语句用于在 MySQL 中创建数据库。在下面的实例中&#xff0c;创建了一个名为 "myDB" 的数据库&#xff1a;实例 (…

.net mysql 类库_(精华)2020年6月27日 C#类库 MySqlHelper(Ado.net数据库封装)

using EFCore.Sharding;using MySql.Data.MySqlClient;using System;using System.Collections.Generic;using System.Data.Common;namespace Core.Util{////// MySql数据库操作帮助类///public class MySqlHelper : DbHelper{#region 构造函数////// 构造函数////// 完整连接字…

ironpython console怎么用_如何在表單中插入ironpython控制台?

I want to make a winform by C#, and add a ironpython console window in it, like a multiline textbox. So I can write python program into it to do some operations in my Winform software.我想通過C&#xff03;進行winform&#xff0c;並在其中添加一個ironpython控…

mysql修改客户端编码命令_mysql命令行修改字符编码

1、修改数据库字符编码mysql> alter database mydb character set utf8 ;2、创建数据库时&#xff0c;指定数据库的字符编码mysql> create database mydb character set utf8 ;3、查看mysql数据库的字符编码mysql> show variables like character%; //查询当前mysql数…

mysql 查看运行级别_运行级别及进程

/etc/rc.d/rc.sysinit由init进程调用执行完成设置网络、主机名、加载文件系统等初始化工作/etc/rc.d/rc脚本文件由init进程调用执行根据指定的运行级别, 加载或终止相应的系统服务/etc/rc.local脚本文件由rc脚本调用执行保存用户定义的需开机后自动执行的命令默认的7种运行级别…

中班机器人歌曲_机器人幼儿园大班音乐教案

机器人幼儿园大班音乐教案作为一名无私奉献的老师&#xff0c;有必要进行细致的教案准备工作&#xff0c;教案是教学活动的总的组织纲领和行动方案。那么问题来了&#xff0c;教案应该怎么写&#xff1f;以下是小编为大家收集的机器人幼儿园大班音乐教案&#xff0c;供大家参考…

java 主线程等待_Java实现主线程等待子线程

本文介绍两种主线程等待子线程的实现方式&#xff0c;以5个子线程来说明&#xff1a;1、使用Thread的join()方法&#xff0c;join()方法会阻塞主线程继续向下执行。2、使用Java.util.concurrent中的CountDownLatch&#xff0c;是一个倒数计数器。初始化时先设置一个倒数计数初始…

java四个权限_java四种访问权限

引言Java中的访问权限理解起来不难&#xff0c;但完全掌握却不容易&#xff0c;特别是4种访问权限并不是任何时候都可以使用。下面整理一下&#xff0c;在什么情况下&#xff0c;有哪些访问权限可以允许选择。一、访问权限简介访问权限控制&#xff1a; 指的是本类及本类内部的…

java map removeall_Java删除Map中元素

前言&#xff1a;关于Java从Map中删除元素的使用&#xff0c;可以使用删除单个元素的事实Map.remove。示例&#xff1a;初始化一个Map对象Map map new HashMap<>();map.put(1, "value 1");map.put(2, "value 2");map.put(3, "value 3");m…

java中0x07_JAVA里0X00的表示

相信很多针对报文进行组织与拆解&#xff0c;在C、C里有memset的功能很容易完成字符串里填充0x00&#xff0c;在java里同样很容易做到&#xff0c;则是用\000,八进制来表示。测试代码如下&#xff1a;package j8583.example;import java.util.ArrayList;import java.util.Array…

java nio集群_java – Hazelcast:连接到远程集群

14:58:26.717 [main] INFO c.m.b.p.s.s.HazelcastCacheClient – creatingnew Hazelcast instance14:58:26.748 [main] INFO com.hazelcast.core.LifecycleService –HazelcastClient[hz.client_0_dev][3.2.1] is STARTING14:58:27.029 [main] INFO com.hazelcast.core.Lifecyc…