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 = utf8create 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
fromjiankunking_account
inner join jiankunking_account_customer onjiankunking_account.id = jiankunking_account_customer.account_id
wherejiankunking_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 transactionat 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 transactionat 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 00: 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

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

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

相关文章

基于Python flask的豆瓣电影数据分析可视化系统,功能多,LSTM算法+注意力机制实现情感分析,准确率高达85%

研究背景 随着数字化时代的到来&#xff0c;电影产业正迎来新的发展机遇和挑战。基于Python Flask的豆瓣电影数据分析可视化系统的研究背景凸显了对电影数据的深度分析和情感挖掘的需求。该系统功能丰富&#xff0c;不仅实现了多样化的数据分析功能&#xff0c;还结合了LSTM算…

2024/5/23 学习杂记

目录 位运算与逻辑运算读程序练习 在switchcase 语句中能否使用continue关键字&#xff1f;为什么&#xff1f; 为什么尽量不使用goto语句? void i与i i和i 哪个效率更高&#xff1f; 良好的条件比较语句风格 memcpy memset 位运算与逻辑运算读程序练习 int x 3, y…

如何解决Redis缓存击穿?

Redis缓存击穿问题,也称作热点Key问题,通常发生在高并发场景下,当一个被高并发访问且缓存重建业务较复杂的key突然失效时,大量请求会同时访问数据库,导致数据库压力瞬间增大。以下是解决Redis缓存击穿问题的几种方案: 使用锁(互斥锁): 原理:当缓存失效时,不是所有线…

CTF| 格式化字符串漏洞

格式化字符串漏洞是PWN题常见的考察点&#xff0c;仅次于栈溢出漏洞。漏洞原因&#xff1a;程序使用了格式化字符串作为参数&#xff0c;并且格式化字符串为用户可控。其中触发格式化字符串漏洞函数主要是printf、sprintf、fprintf、prin等C库中print家族的函数 0x01 格式化字符…

双非二本找工作前的准备day28

学习目标&#xff1a; 每天复习代码随想录上的题目2-3道算法&#xff08;时间充足可以继续&#xff09; 今日碎碎念&#xff1a; 1&#xff09;进入贪心与dp专题&#xff0c;过完准备二刷&#xff0c;以及刷剑指offer。 2&#xff09;这两天没更新是休息一下&#xff0c;然后…

如何深入理解、应用及扩展 Twemproxy?no.15

Twemproxy 架构及应用 Twemproxy 是 Twitter 的一个开源架构&#xff0c;它是一个分片资源访问的代理组件。如下图所示&#xff0c;它可以封装资源池的分布及 hash 规则&#xff0c;解决后端部分节点异常后的探测和重连问题&#xff0c;让 client 访问尽可能简单&#xff0c;同…

C语言之宏详解(超级详细!)

目录 一、用宏前须知-#define相关知识 大致结构&#xff1a; 对预定义符号的补充&#xff1a; 二、用#define定义宏 什么是宏&#xff1f; #define的替换规则&#xff1a; 三、常用的宏定义 1、宏定义常量 2、定义一个宏语句 3、宏定义函数 宏与函数的对比&#xff1a; …

29【PS 作图】宫灯 夜景转换

夜景转化 1 原图 2 选中要变换的图层,然后点击“颜色查找” 再3DLUT文件中,选择moonlight.3DL,可以快速把图层变成偏夜景的颜色 结果如下: 3 选择“曲线” 把曲线 右边往上调【亮的更亮】,左边往下调【暗的更暗】 4 添加灯光 新建一个图层

前端面试题大合集8----性能优化篇

一、哪些方法可以提升网站前端性能 1、Http请求优化 主要分为减少Http请求次数&#xff0c;减小请求数据量和缓存三方面。 减少Http请求次数&#xff0c;可以通过以下方法实现&#xff1a; 合并js、css文件&#xff1b;使用css-spirites技术合并图片&#xff1b;压缩图片大…

HTML+CSS+JS简易计算器

HTMLCSSJS简易计算器 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>简易计算器</t…

AAA实验配置

一、实验目的 掌握AAA本地认证的配置方法 掌握AAA本地授权的配置方法 掌握AAA维护的方法 1.搭建实验拓扑图 2.完成基础配置&#xff1a; 3.使用ping命令测试两台设备的连通性&#xff1a; 二、配置AAA 1.打开R1&#xff1a;配置AAA方案 这两个方框内的可以改名&#xff0c…

百度页面奔跑的白熊html、css

一、相关知识-动画 1.基本使用&#xff1a;先定义再调用 2. 调用动画 用keyframes定义动画&#xff08;类似定义类选择器&#xff09; keyframes动画名称{ 0%{ width:100px&#xff1b; } 100%{ width:200px; } } 使用动画 div { width:200px; height:200px; background-…

前端面试题日常练-day28 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末。 1. 在Vue中&#xff0c;以下哪个选项用于监听组件生命周期钩子函数&#xff1f; a) watch b) computed c) lifecycle d) created 2. 在Vue中&#xff0c;以下哪个选项用于在列表渲染时为每个元素…

Pytorch线性模型(Linear Model)

基本步骤 ①首先准备好数据集&#xff08;DataSet&#xff09; ②模型的选择或者设计&#xff08;Model&#xff09; ③进行训练&#xff08;Train&#xff09;大部分模型都需要训练&#xff0c;有些不需要。这一步后我们会确定不同特征的权重 ④推理&#xff08;inferring…

开封旅游三天两夜旅游攻略

开封是一座历史悠久的城市&#xff0c;有着丰富的文化遗产和美食。以下是一个三天两夜的开封旅游攻略&#xff0c;供你参考&#xff1a; 一、行程安排 第一天&#xff1a; 上午&#xff1a;抵达开封&#xff0c;前往酒店办理入住手续。随后参观开封博物馆&#xff0c;了解开封…

【Python安全攻防】【网络安全】一、常见被动信息搜集手段

一、IP查询 原理&#xff1a;通过目标URL查询目标的IP地址。 所需库&#xff1a;socket Python代码示例&#xff1a; import socketip socket.gethostbyname(www.163.com) print(ip)上述代码中&#xff0c;使用gethostbyname函数。该函数位于Python内置的socket库中&#xf…

广场舞团|基于SprinBoot+vue的广场舞团系统(源码+数据库+文档)

广场舞团系统 目录 基于SprinBootvue的广场舞团系统 一、前言 二、系统设计 三、系统功能设计 1 系统功能模块 2 后台登录模块 5.2.1管理员功能模块 5.2.2社团功能模块 5.2.3用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推…

Pytorch-06 使用GPU加速计算

要在PyTorch中使用GPU加速计算&#xff0c;需要将模型和数据移动到GPU上进行处理。以下是上一节演示修改后的示例代码&#xff0c;展示了如何在训练过程中利用GPU加速计算&#xff1a; import torch import torch.nn as nn import torch.optim as optim import time# 检查GPU是…

2024-05-28 问AI: 在深度学习中,什么是反向随机失活?

文心一言 在深度学习中&#xff0c;反向随机失活&#xff08;Inverse Randomized Elimination&#xff0c;通常称为Dropout&#xff09;是一种在训练深度神经网络时常用的正则化技术&#xff0c;用于防止过拟合。该技术通过随机将神经网络中的一部分神经元“失活”或“丢弃”来…

深度剖析:为什么 Spring 和 IDEA 都不推荐使用 @Autowired 注解

目录 依赖注入简介 Autowired 注解的优缺点 Spring 和 IDEA 不推荐使用 Autowired 的原因 构造器注入的优势 Autowired 注解的局限性 可读性和可测试性的问题 推荐的替代方案 构造器注入 Setter 注入 Java Config Bean 注解 项目示例&#xff1a;Autowired vs 构造器…