MySQL select for update 加锁

news2025/3/18 12:33:20

背景

当多人操作同一个客户下账号的时候,希望顺序执行,某个时刻只有一个人在操作;当然可以通过引入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

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

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

相关文章

amis 联动效果触发的几种方式

联动效果实现主要俩种方式: 1.表达式实现联动,基于组件内或数据链的变量变化的联动 比如&#xff1a; "source": "/amis/api/mock2/options/level2?name${name} " (必须是这种字符串拼接形式,在data数据映射中表达式不会触发联动) 所有初始化接口链…

【FPGA】Verilog:解码器 | 编码器 | 多路复用器(Mux, Multiplexer)

0x00 什么是解码器 解码器是根据输入信号在多个输出位中选择一个输出位的装置。例如,当解码器接收2位二进制值作为输入时,它可以接收00、01、10、11四种输入值,并根据每个输入值在4个输出位中选择一个,输出为1000、0100、0010、0001中的一种。这样的解码器被称为高电平有效…

【数据挖掘】四分位数识别数据中的异常值(附代码)

写在前面&#xff1a; 首先感谢兄弟们的订阅&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

Android四大组件 Broadcast广播机制

一 概述 广播 (Broadcast) 机制用于进程或线程间通信&#xff0c;广播分为广播发送和广播接收两个过程&#xff0c;其中广播接收者 BroadcastReceiver 是 Android 四大组件之一。BroadcastReceiver 分为两类&#xff1a; 静态广播接收者&#xff1a;通过 AndroidManifest.xm…

开源模型应用落地-食用指南-以最小成本博最大收获

一、背景 时间飞逝&#xff0c;我首次撰写的“开源大语言模型-实际应用落地”专栏已经完成了一半以上的内容。由衷感谢各位朋友的支持,希望这些内容能给正在学习的朋友们带来一些帮助。 在这里&#xff0c;我想分享一下创作这个专栏的初心以及如何有效的&#xff0c;循序渐进的…

机器视觉-硬件

机器视觉-硬件 镜头焦距凸透镜焦点不止一个相机镜头由多个镜片组成对焦和变焦 镜头光圈光圈的位置光圈系数F 镜头的景深景深在光路中的几何意义 远心镜头远心镜头的种类远心镜头特性应用场景 镜头的分辨率镜头反差镜头的MTF曲线镜头的靶面尺寸镜头的几何相差相机镜头接口螺纹接…

私域流量的真谛:构建并运营属于你自己的私域生态

大家好&#xff0c;我是来自一家专注于私域电商行业的软件开发公司的产品经理&#xff0c;拥有超过七年的行业经验。今天&#xff0c;我想和大家聊聊私域流量的真正含义&#xff0c;以及为何我们应该关注并努力打造属于自己的私域生态。 什么是私域流量&#xff1f; 私域流量&…

文心大模型4.0创建智能体:资深研发专家一对一辅导

目录 前言 一、什么是文心智能体平台&#xff1f; 1、通过平台能做什么 2、平台的优势 3、智能体类型 二、如何访问和使用这个智能体&#xff1f; 1、零代码开发&#xff1a;一句话创建智能体 2、资深研发专家一对一辅导智能体介绍 总结 前言 在当今快节奏和高度竞争的…

【高时效通路】

一 高时效通路 1.1 pathchdumper 实时数据拉取、实时数据处理、5分钟微批dump来加速时效性&#xff0c;具体来说&#xff1a; 实时数据拉取&#xff08;Fetcher&#xff09;&#xff1a;基于Databus Fetcher基建&#xff0c;直接对接F0层实时拉取最新数据&#xff0c;保证该…

哥白尼哨兵系列卫星数据不能下载的解决方法

自2023年1月24日起&#xff0c;一个新的哥白尼数据空间生态系统已经启动&#xff0c;为所有哨兵数据&#xff08;Sentinel-1, Sentinel-2, Sentinel-3 and Sentinel-5P&#xff09;提供可视化和数据处理&#xff0c;地址为&#xff1a;https://dataspace.copernicus.eu/。详细介…

Linux驱动(2)---Linux内核的组成

1.Linux内核源码目录 arch包含和硬件体系相关结构相关源码&#xff0c;每个平台占用一个目录 block&#xff1a;块设备驱动程序I/O调度 crypto&#xff1a;常用加密和三列算法&#xff0c;还有一些压缩和CRC校验算法。 documentation:内核个部分的通用解释和注释.。 drive…

护眼小贴士:学生如何正确使用台灯?

随着电子设备的普及和长时间的用眼&#xff0c;长时间盯着屏幕或学习&#xff0c;眼睛需要不断调节焦距&#xff0c;导致眼睛肌肉疲劳&#xff0c;进而引发视力下降。这种现象在年轻一代甚至青少年中尤为普遍&#xff0c;这种疲劳状态不仅影响眼睛的舒适度&#xff0c;还会导致…

【Linux】网络层——IP协议

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;Linux 目录 &#x1f449;&#x1f3fb;IP协议基本概念&#x1f449;&#x1f3fb;IP的协议头格式&#x1f449;&#x1f3fb;IP协议的网段划分五类IP地址子…

fastapi中实现多个路由请求

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 前言 最近在写机器人相关的接口&#xff0c;顺手学了学python&#xff0c;发现这是个好东西&#xff0c;写代码效率比java要高很多&#xff0c;比如写个词云呀&#xff0c;写个回调呀&am…

从参数变化解读 MySQL 8.2.0 发版说明

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 日前&#xff0c;MySQL 8.2.0 创新版本已正式上线&#xff0c;并提供安装包下载&#xff0c;但 docker 镜像尚未更新。 在 MySQL 8.1.0 刚发版时也做过分析&#xff0c;欢迎阅读&#xff1a; 重…

云部署最简单python web

最近在玩云主机&#xff0c;考虑将简单的web应用装上去&#xff0c;通过广域网访问一下&#xff0c;代码很简单&#xff0c;所以新手几乎不会碰到什么问题。 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return Hello, World!app.route(/gree…

html通过数据改变,图片跟着改变

改变前 改变后 通过数据来控制样式展示 <template><div>通过num控制图标是否更改{{num}}<div class"box"><!-- 如果num大于1则是另一种&#xff0c;样式&#xff0c;如果小时1&#xff0c;则是另一种样式 --><div class"item&qu…

字节面试:百亿级数据存储,怎么设计?只是分库分表吗?

尼恩&#xff1a;百亿级数据存储架构起源 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;经常性的指导小伙伴们改造简历。 经过尼恩的改造之后&#xff0c;很多小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试机会&#xff0c…

WGCLOUD可以使用短信告警通知吗

支持的 以下是官网的说明 告警报警配置说明 - WGCLOUD

2024.5.25晚训题解

这套题挺简单的。。。 A题 AC率差不多100% B题 AC率差不多75% C题 AC率也差不多75% D题 AC率 50% E题 AC率 25% 向着top 1%出发 A题题解 Stair, Peak, or Neither? 简单判断题&#xff0c;自己写 #include<bits/stdc.h> using namespace std; int A[5]; int main() {…