MySQL select for update 加锁

背景

当多人操作同一个客户下账号的时候,希望顺序执行,某个时刻只有一个人在操作;当然可以通过引入redis这种中间件实现,但考虑到并发不会很多,所以不想再引入别的中间件。

表结构

create table `jiankunking_account` (
  `id` bigint(20) not null auto_increment COMMENT '',
  `name` varchar(100) not null,
  `email` varchar(255) default '' COMMENT '邮箱',
  `phone_number` varchar(11) default '' COMMENT '手机号',
  `last_login_at` timestamp NULL DEFAULT NULL COMMENT '最后登陆时间',
  primary key (`name`),
  unique key `id` (`id`),
  unique key `account_name` (`name`)
        using BTREE,
  key `phone_number` (`phone_number`),
  key `updated_at` (`updated_at`)
) engine = InnoDB auto_increment = 6786111 default CHARSET = utf8


create table `jiankunking_account_customer` (
  `account_id` bigint(20) not null COMMENT '账户id',
  `customer_id` varchar(40) not null default '' COMMENT '客户id',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  primary key (`account_id`,
`customer_id`),
  key `account_id` (`account_id`)
        using BTREE,
  key `customer_id` (`customer_id`)
        using BTREE
) engine = InnoDB default CHARSET = utf8

数据库自动提交

先看下数据库自动提交有没有关闭

show variables like  'autocommit' ;

验证SQL

事务一、二 开两个终端或者在DBvear开两个窗口

事务一

START TRANSACTION; // 第一步

select // 第三步
	jiankunking_account.id,
	jiankunking_account.NAME,
	jiankunking_account.phone_number,
	jiankunking_account_customer.customer_id
from
	jiankunking_account
inner join jiankunking_account_customer on
	jiankunking_account.id = jiankunking_account_customer.account_id
where
	jiankunking_account_customer.customer_id = '11' for
update;

commit;

事务二

START TRANSACTION;// 第二步

update  jiankunking_account  set last_login_at =now() where id ='2';//第四步

// delete from jiankunking_account  where id='2';//删除这种情况也会夯住
// 这里操作 jiankunking_account_customer表中customer_id = '11'的数据也会被夯住

commit;

两个事务执行顺序按照SQL后面的指定,当指定到第三步的时候,能获取到具体数据
在这里插入图片描述
在执行第3步的时候会卡住
在这里插入图片描述
等到超时时间后,会提示错误

org.jkiss.dbeaver.model.sql.DBSQLException: SQL 错误 [1205] [40001]: Lock wait timeout exceeded; try restarting transaction
	at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCStatementImpl.executeStatement(JDBCStatementImpl.java:133)
	at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.executeStatement(SQLQueryJob.java:614)
	at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.lambda$2(SQLQueryJob.java:505)
	at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.executeSingleQuery(SQLQueryJob.java:527)
	at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.extractData(SQLQueryJob.java:976)
	at org.jkiss.dbeaver.ui.editors.sql.SQLEditor$QueryResultsContainer.readData(SQLEditor.java:4155)
	at org.jkiss.dbeaver.ui.controls.resultset.ResultSetJobDataRead.lambda$0(ResultSetJobDataRead.java:123)
	at org.jkiss.dbeaver.model.exec.DBExecUtils.tryExecuteRecover(DBExecUtils.java:194)
	at org.jkiss.dbeaver.ui.controls.resultset.ResultSetJobDataRead.run(ResultSetJobDataRead.java:121)
	at org.jkiss.dbeaver.ui.controls.resultset.ResultSetViewer$ResultSetDataPumpJob.run(ResultSetViewer.java:5148)
	at org.jkiss.dbeaver.model.runtime.AbstractJob.run(AbstractJob.java:115)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:124)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:767)
	at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:652)
	at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCStatementImpl.execute(JDBCStatementImpl.java:330)
	at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCStatementImpl.executeStatement(JDBCStatementImpl.java:131)
	... 11 more

锁情况

查询在锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

更新

[
	{
		"trx_id": "322316562",
		"trx_state": "LOCK WAIT",
		"trx_started": "2024-05-22 18:18:35",
		"trx_requested_lock_id": "322316562:267:338:81",
		"trx_wait_started": "2024-05-22 18:18:35",
		"trx_weight": 2,
		"trx_mysql_thread_id": 9612611,
		"trx_query": "/* ApplicationName=DBeaver 24.0.5 - SQLEditor <Script-8.sql> */ update  jiankunking_account  set last_login_at =now() where id ='2'",
		"trx_operation_state": "starting index read",
		"trx_tables_in_use": 1,
		"trx_tables_locked": 1,
		"trx_lock_structs": 2,
		"trx_lock_memory_bytes": 1136,
		"trx_rows_locked": 1,
		"trx_rows_modified": 0,
		"trx_concurrency_tickets": 0,
		"trx_isolation_level": "READ COMMITTED",
		"trx_unique_checks": 1,
		"trx_foreign_key_checks": 1,
		"trx_last_foreign_key_error": null,
		"trx_adaptive_hash_latched": 0,
		"trx_adaptive_hash_timeout": 0,
		"trx_is_read_only": 0,
		"trx_autocommit_non_locking": 0
	},
	{
		"trx_id": "322316561",
		"trx_state": "RUNNING",
		"trx_started": "2024-05-22 18:18:30",
		"trx_requested_lock_id": null,
		"trx_wait_started": null,
		"trx_weight": 20,
		"trx_mysql_thread_id": 9612580,
		"trx_query": null,
		"trx_operation_state": null,
		"trx_tables_in_use": 0,
		"trx_tables_locked": 2,
		"trx_lock_structs": 20,
		"trx_lock_memory_bytes": 3520,
		"trx_rows_locked": 36,// 注意这里的行数比实际行数大,实际行数应该是18行,jiankunking_account 9行,jiankunking_account_customer9行
		"trx_rows_modified": 0,
		"trx_concurrency_tickets": 0,
		"trx_isolation_level": "READ COMMITTED",
		"trx_unique_checks": 1,
		"trx_foreign_key_checks": 1,
		"trx_last_foreign_key_error": null,
		"trx_adaptive_hash_latched": 0,
		"trx_adaptive_hash_timeout": 0,
		"trx_is_read_only": 0,
		"trx_autocommit_non_locking": 0
	}
]

删除

[
  {
    "trx_id": "322316782",
    "trx_state": "LOCK WAIT",
    "trx_started": "2024-05-22 18:22:58",
    "trx_requested_lock_id": "322316782:267:338:81",
    "trx_wait_started": "2024-05-22 18:22:58",
    "trx_weight": 2,
    "trx_mysql_thread_id": 9612611,
    "trx_query": "/* ApplicationName=DBeaver 24.0.5 - SQLEditor <Script-8.sql> */ delete from jiankunking_account  where id='2'",
    "trx_operation_state": "starting index read",
    "trx_tables_in_use": 1,
    "trx_tables_locked": 1,
    "trx_lock_structs": 2,
    "trx_lock_memory_bytes": 1136,
    "trx_rows_locked": 1,
    "trx_rows_modified": 0,
    "trx_concurrency_tickets": 0,
    "trx_isolation_level": "READ COMMITTED",
    "trx_unique_checks": 1,
    "trx_foreign_key_checks": 1,
    "trx_last_foreign_key_error": null,
    "trx_adaptive_hash_latched": 0,
    "trx_adaptive_hash_timeout": 0,
    "trx_is_read_only": 0,
    "trx_autocommit_non_locking": 0
  },
  {
    "trx_id": "322316781",
    "trx_state": "RUNNING",
    "trx_started": "2024-05-22 18:22:49",
    "trx_requested_lock_id": null,
    "trx_wait_started": null,
    "trx_weight": 20,
    "trx_mysql_thread_id": 9612580,
    "trx_query": null,
    "trx_operation_state": null,
    "trx_tables_in_use": 0,
    "trx_tables_locked": 2,
    "trx_lock_structs": 20,
    "trx_lock_memory_bytes": 3520,
    "trx_rows_locked": 36,// 注意这里的行数比实际行数大,实际行数应该是18行,jiankunking_account 9行,jiankunking_account_customer9行
    "trx_rows_modified": 0,
    "trx_concurrency_tickets": 0,
    "trx_isolation_level": "READ COMMITTED",
    "trx_unique_checks": 1,
    "trx_foreign_key_checks": 1,
    "trx_last_foreign_key_error": null,
    "trx_adaptive_hash_latched": 0,
    "trx_adaptive_hash_timeout": 0,
    "trx_is_read_only": 0,
    "trx_autocommit_non_locking": 0
  }
]

那这里的锁到底是什么锁?

SHOW ENGINE INNODB STATUS;

可以看到锁信息如下

---TRANSACTION 322359005, ACTIVE 19 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 9743399, OS thread handle 140157041190656, query id 1442147372 10.192.26.59 jkk updating
/* ApplicationName=DBeaver 24.0.5 - SQLEditor <Script-8.sql> */ update jiankunking_account set last_login_at =now() where id='2'
------- TRX HAS BEEN WAITING 19 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 267 page no 338 n bits 736 index id of table `jkk`.`jiankunking_account` trx id 322359005 lock_mode X locks rec but not gap waiting
Record lock, heap no 81 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 8; hex 80000000009c0fde; asc         ;;
 1: len 10; hex 38383030303030303031; asc 8800000001;;

------------------
---TRANSACTION 322359002, ACTIVE 23 sec
20 lock struct(s), heap size 3520, 36 row lock(s)
MySQL thread id 9742898, OS thread handle 140156937144064, query id 1442147268 10.192.26.59 jkk
--------
--------

如果jiankunking_account_customer用created_at字段(注意:没有索引)来过滤数据,继续上面的操作,在锁信息中可以看到,还是行锁,并不是网上说的表锁;如果有自己的应用场景还是要按照自己的业务场景验证下。

结论

通过简单的select for update 可以实现在并发不高的情况锁住数据。

官方文档:

  • https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
  • https://dev.mysql.com/doc/refman/8.0/en/information-schema-innodb-trx-table.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

肆拾玖坊FFC模式,社群裂变,股权众筹设计

肆拾玖坊商业模式&#xff0c;白酒新零售体系&#xff0c;众筹合伙模式 坐标&#xff1a;厦门&#xff0c;我是易创客肖琳 深耕社交新零售行业10年&#xff0c;主要提供新零售系统工具及顶层商业模式设计、全案策划运营陪跑等。 联想高管辞职跑去卖酒&#xff0c;6年狂赚30亿&…

手机“本地”也能玩转AI大模型 - 万物皆可AI

友友们&#xff0c;大家好&#xff01;我最近发现一个很有意思的AI项目——MiniCPM-V&#xff0c;可以说它将AI技术的应用推向了一个全新的高度&#xff0c;让我们能够将GPT-4V级的多模态大模型直接部署在我们的手机上&#xff0c;而且完全不需要联网&#xff0c;真正的手机本地…

Unity版本使用情况统计(更新至2024年4月)

UWA发布&#xff5c;本期UWA发布的内容是第十四期Unity版本使用统计&#xff0c;统计周期为2023年11月至2024年4月&#xff0c;数据来源于UWA网站&#xff08;www.uwa4d.com&#xff09;性能诊断提测的项目。希望给Unity开发者提供相关的行业趋势作为参考。 2023年11月 - 2024年…

C++候捷stl-视频笔记1

认识headers、版本、重要资源 STL的核心思想是泛型编程 新式头文件内的组件封装在命名空间std中&#xff1a; using namespace std; using std::cout;或std::vector vec; 旧式头文件内的组件不封装在命名空间std中 注:不建直接使用using namespace xxx&#xff0c;如果使用的…

apexcharts数据可视化之极坐标区域图

apexcharts数据可视化之极坐标区域图 有完整配套的Python后端代码。 本教程主要会介绍如下图形绘制方式&#xff1a; 基础极坐标区域图单色极坐标区域图 基础极坐标区域图 import ApexChart from react-apexcharts;export function BasicPolar() {// 数据序列const series…

深入解析多维数组与主对角线元素之和

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;多维数组的奥秘 二、多维数组的基本概念 1. 定义与创建 2. 维度与形…

Linux服务器安装docker,基于Linux(openEuler、CentOS8)

本实验环境为openEuler系统(以server方式安装)&#xff08;CentOS8基本一致&#xff0c;可参考本文) 目录 知识点实验 知识点 Docker 是一个开源的应用容器引擎。它允许开发者将应用及其所有依赖项打包到一个可移植的容器中&#xff0c;并发布到任何支持Docker的流行Linux或Wi…

歌曲转换成mp3格式超简单!快来试试看

在数字音乐时代&#xff0c;我们经常从各种来源下载或收藏到各种音频文件&#xff0c;但有时这些文件可能并不是我们设备所支持的常见格式&#xff0c;尤其是当我们更倾向于使用MP3格式的时候。因此&#xff0c;对于那些希望统一音乐库格式的人来说&#xff0c;将歌曲转换成mp3…

redis面试知识点

Redis知识点 Redis的RDB和AOF机制各是什么&#xff1f;它们有什么区别&#xff1f; 答&#xff1a;Redis提供了RDB和AOF两种数据持久化机制&#xff0c;适用于不同的场景。 RDB是通过在特定的时刻对内存中的完整的数据复制快照进行持久化的。 RDB工作原理&#xff1a; 当执行…

深入理解深度学习中的激活层:Sigmoid和Softmax作为非终结层的应用

深入理解深度学习中的激活层&#xff1a;Sigmoid和Softmax作为非终结层的应用Sigmoid 和 Softmax 激活函数简介Sigmoid函数Softmax函数 Sigmoid 和 Softmax 作为非终结层多任务学习特征变换增加网络的非线性实际案例 注意事项结论 深入理解深度学习中的激活层&#xff1a;Sigmo…

探索研究大语言在生物识别技术——使用ChatGP-4从完成从人脸识别到年龄估计

0.引言 论文提出以下几要点&#xff1a; &#xff08;1&#xff09;. 人脸识别、性别检测和年龄估计的性能评估&#xff1a; 进行了一项研究&#xff0c;使用GPT-4这样的大型语言模型来处理人脸识别、性别检测和年龄估计等任务。这些任务是生物识别技术中的常见应用&#xff…

【评测体验】OrangePi AIpro 系统构建及性能测试

感谢香橙派社区能够邀请我评测这款开发板&#xff0c;祝愿国产开发板发展越来越好&#xff01;在这里能够尽自己的一份力量是我的荣幸。 这篇文章是 OrangePi AIpro 开发板的评测&#xff0c;内容包括开发板简介、系统构建过程、系统性能测试、压缩算法性能测试、内核编译。 到…

分析和设计算法

目录 前言 循环不变式 n位二进制整数相加问题 RAM模型 使用RAM模型分析 代码的最坏情况和平均情况分析 插入排序最坏情况分析 插入排序平均情况分析 设计算法 分治法 总结 前言 循环迭代&#xff0c;分析算法和设计算法作为算法中的三个重要的角色&#xff0c;下面…

【深度 Q 学习-01】 Q学习概念和python实现

文章目录 一、说明二、深度 Q 学习概念三、python实现四、结论 关键词&#xff1a;Deep Q-Networks 一、说明 在强化学习 &#xff08;RL&#xff09; 中&#xff0c;Q 学习是一种基础算法&#xff0c;它通过学习策略来最大化累积奖励&#xff0c;从而帮助智能体导航其环境。它…

2024年618网购节各大电商超级红包二维码集合

一年一度的电商618网购节又要来了&#xff0c;下面收集了淘宝/京东/拼多多的618红包二维码&#xff0c;手机扫描或识别即可每天领红包&#xff0c;可参考好物分享中的商品下单&#xff1a; 淘宝618超级红包&#xff1a;即日起至2024.6.10&#xff0c;每天可领一次 京东618无门…

P9 【力扣+知识点】【算法】【二分查找】C++版

【704】二分查找&#xff08;模板题&#xff09;看到复杂度logN&#xff0c;得想到二分 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0…

RUST 和 GO 如何管理它们的内存

100编程书屋_孔夫子旧书网 Go 中的内存管理 Go 中的内存不会在缓存键被驱逐时立即释放。 相反&#xff0c;垃圾收集器会经常运行以发现任何没有引用的内存并释放它。 换句话说&#xff0c;内存会一直挂起&#xff0c;直到垃圾收集器可以评估它是否真正不再使用&#xff0c;而…

SpringCloud:Nacos配置管理

程序员老茶 &#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; P   S : 点赞是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#…

01--nginx基础

前言&#xff1a; 本文用来整理一下nginx的用法&#xff0c;应该是本人中间件专栏的第一篇文章&#xff0c;这里开始概念和实操将会同样重要&#xff0c;面试时基本概念的理解非常重要&#xff0c;深有体会&#xff0c;不会再让概念成为压死骆驼的稻草。 1、nginx简介 Nginx…

vue连接mqtt实现收发消息组件超级详细

基本概念&#xff1a; MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种基于发布/订阅模式的轻量级消息传输协议&#xff0c;专为低带宽、高延迟或不稳定的网络环境设计。以下是MQTT实现收发消息的基本原理&#xff1a; 客户端-服务器模型&#xff1a…