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.pswp.cn/bicheng/18193.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/18193.shtml
英文地址,請注明出處:http://en.pswp.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 構造器…