搜尋
首頁資料庫mysql教程一起徹底搞懂 MySQL 的鎖機制

一起徹底搞懂 MySQL 的鎖機制

Mar 31, 2021 am 09:38 AM
mysql鎖機制

一起徹底搞懂 MySQL 的鎖機制

鎖定在MySQL中作為非常重要的部分,而鎖定對MySQL的資料存取權有舉重的影響。鎖涉及到的知識篇幅也很多,所以要啃完並消化到自己的肚子裡,是需要靜下心好好反反复復幾遍地細細品味。本文是對鎖的一個大概的整理,一些相關深入的細節,還是需要找到相關書籍來繼續夯實。

一张图彻底搞懂 MySQL 的锁机制

相關免費學習推薦:mysql影片教學

#鎖定的認知

1.1 鎖的解釋

计算机协调多个进程或线程并发访问某一资源的机制。

1.2 鎖定的重要性

在数据库中,除传统计算资源(CPU、RAM、I\O等)的争抢,数据也是一种供多用户共享的资源。
如何保证数据并发访问的一致性,有效性,是所有数据库必须要解决的问题。
锁冲突也是影响数据库并发访问性能的一个重要因素,因此锁对数据库尤其重要。

1.3 鎖定的缺點

加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否已解除、释放锁等 ,都会增加系统的开销。

1.4 簡單的範例

现如今网购已经特别普遍了,比如淘宝双十一活动,当天的人流量是千万及亿级别的,但商家的库存是有限的。
系统为了保证商家的商品库存不发生超卖现象,会对商品的库存进行锁控制。当有用户正在下单某款商品最后一件时,
系统会立马对该件商品进行锁定,防止其他用户也重复下单,直到支付动作完成才会释放(支付成功则立即减库存售罄,支付失败则立即释放)。

鎖定的類型

2.1 表鎖定

#
读锁(read lock),也叫共享锁(shared lock)
针对同一份数据,多个读操作可以同时进行而不会互相影响(select)
写锁(write lock),也叫排他锁(exclusive lock)
当前操作没完成之前,会阻塞其它读和写操作(update、insert、delete)

儲存引擎預設鎖定##

MyISAM

特點

1. 对整张表加锁
2. 开销小
3. 加锁快
4. 无死锁
5. 锁粒度大,发生锁冲突概率大,并发性低
結論

1. 读锁会阻塞写操作,不会阻塞读操作
2. 写锁会阻塞读和写操作

建議

#
MyISAM的读写锁调度是写优先,这也是MyISAM不适合做写为主表的引擎,因为写锁以后,其它线程不能做任何操作,大量的更新使查询很难得到锁,从而造成永远阻塞。

2.2 行鎖定

類型

读锁(read lock),也叫共享锁(shared lock)
允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
写锁(write lock),也叫排他锁(exclusive lock)
允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享锁和排他锁
意向共享锁(IS)
一个事务给一个数据行加共享锁时,必须先获得表的IS锁
意向排它锁(IX)
一个事务给一个数据行加排他锁时,必须先获得该表的IX锁
儲存引擎預設鎖定

InnoDB

特點

1. 对一行数据加锁
2. 开销大
3. 加锁慢
4. 会出现死锁
5. 锁粒度小,发生锁冲突概率最低,并发性高

交易並發帶來的問題

1. 更新丢失
解决:让事务变成串行操作,而不是并发的操作,即对每个事务开始---对读取记录加排他锁
2. 脏读
解决:隔离级别为Read uncommitted
3. 不可重读
解决:使用Next-Key Lock算法来避免
4. 幻读
解决:间隙锁(Gap Lock)

2.3 頁鎖定

开销、加锁时间和锁粒度介于表锁和行锁之间,会出现死锁,并发处理能力一般(此锁不做多介绍)

如何上鎖?

3.1 表鎖

隱含上鎖(默認,自動加鎖自動釋放)

select //上读锁
insert、update、delete //上写锁

明確上鎖(手動)

lock table tableName read;//读锁
lock table tableName write;//写锁

解鎖(手動)

unlock tables;//所有锁表

session01session02##lock table teacher read;//上讀鎖定#select * from teacher;  //可以正常讀取#select * from teacher;//可以正常讀取update teacher set name = 3 where id =2;//被封鎖



update teacher set name = 3 where id =2;//報錯因被上讀鎖不能寫動作
unlock tables;//解鎖session01session02#lock table teacher write;//上寫鎖定#select * from teacher;  //可以正常讀取select * from teacher;//被阻塞update teacher set name = 4 where id =2;//被阻塞unlock tables;//解鎖
update teacher set name = 3 where id =2;//更新作業成功


update teacher set name = 3 where id =2;//可以正常更新操作

#select * from teacher;//讀取成功

update teacher set name = 4 where id =2;//更新作業成功隱式上鎖(默認,自動加鎖自動釋放)明確上鎖(手動)
1. 提交事务(commit)
2. 回滚事务(rollback)
3. kill 阻塞进程
session01
3.2 行鎖
select //不会上锁
insert、update、delete //上写锁
select * from tableName lock in share mode;//读锁
select * from tableName for update;//写锁

解鎖(手動)

session02



begin;update teacher set name = 5 where id =2;//被封鎖#commit;#session01session02
select * from teacher where id = 2 lock in share mode;//上讀鎖定

#select * from teacher where id = 2;//可以正常讀取
update teacher set name = 3 where id =2;// 可以更新動作

update teacher set name = 5 where id =2;//更新作業成功

###############begin;### ##################select * from teacher where id = 2 for update;//上寫鎖定################ ##############select * from teacher where id = 2;//可以正常讀取############update teacher set name = 3 where id = 2;// 可以更新操作######update teacher set name = 5 where id =2;//被阻塞###########rollback;######### ######################update teacher set name = 5 where id =2;//更新作業成功############
为什么上了写锁,别的事务还可以读操作?
因为InnoDB有MVCC机制(多版本并发控制),可以使用快照读,而不会被阻塞。

行锁的实现算法

4.1 Record Lock锁

单个行记录上的锁
Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表建立的时候没有设置任何一个索引,这时InnoDB存储引擎会使用隐式的主键来进行锁定

4.2 Gap Lock锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引加锁,对于键值在条件范围内但并不存在的记录。

优点:解决了事务并发的幻读问题
不足:因为query执行过程中通过范围查找的话,他会锁定争个范围内所有的索引键值,即使这个键值并不存在。
间隙锁有一个致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成锁定的时候无法插入锁定键值范围内任何数据。在某些场景下这可能会对性能造成很大的危害。

4.3 Next-key Lock锁

同时锁住数据+间隙锁
在Repeatable Read隔离级别下,Next-key Lock 算法是默认的行记录锁定算法。

4.4 行锁的注意点

1. 只有通过索引条件检索数据时,InnoDB才会使用行级锁,否则会使用表级锁(索引失效,行锁变表锁)
2. 即使是访问不同行的记录,如果使用的是相同的索引键,会发生锁冲突
3. 如果数据表建有多个索引时,可以通过不同的索引锁定不同的行

如何排查锁?

5.1 表锁

查看表锁情况

show open tables;

一张图彻底搞懂 MySQL 的锁机制

表锁分析

show status like 'table%';

一张图彻底搞懂 MySQL 的锁机制

1. table_locks_waited
出现表级锁定争用而发生等待的次数(不能立即获取锁的次数,每等待一次值加1),此值高说明存在着较严重的表级锁争用情况
2. table_locks_immediate
产生表级锁定次数,不是可以立即获取锁的查询次数,每立即获取锁加1

5.2 行锁

行锁分析

show status like 'innodb_row_lock%';

一张图彻底搞懂 MySQL 的锁机制

1. innodb_row_lock_current_waits //当前正在等待锁定的数量
2. innodb_row_lock_time //从系统启动到现在锁定总时间长度
3. innodb_row_lock_time_avg //每次等待所花平均时间
4. innodb_row_lock_time_max //从系统启动到现在等待最长的一次所花时间
5. innodb_row_lock_waits //系统启动后到现在总共等待的次数

information_schema库

1. innodb_lock_waits表
2. innodb_locks表
3. innodb_trx表

优化建议

1. 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2. 合理设计索引,尽量缩小锁的范围
3. 尽可能较少检索条件,避免间隙锁
4. 尽量控制事务大小,减少锁定资源量和时间长度
5. 尽可能低级别事务隔离

死锁

6.1 解释

指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象

6.2 产生的条件

1. 互斥条件:一个资源每次只能被一个进程使用
2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
3. 不剥夺条件:进程已获得的资源,在没有使用完之前,不能强行剥夺
4. 循环等待条件:多个进程之间形成的一种互相循环等待的资源的关系

6.1 解决

1. 查看死锁:show engine innodb status \G
2. 自动检测机制,超时自动回滚代价较小的事务(innodb_lock_wait_timeout 默认50s)
3. 人为解决,kill阻塞进程(show processlist)
4. wait for graph 等待图(主动检测)

6.1 如何避免

1. 加锁顺序一致,尽可能一次性锁定所需的数据行
2. 尽量基于primary(主键)或unique key更新数据
3. 单次操作数据量不宜过多,涉及表尽量少
4. 减少表上索引,减少锁定资源
5. 尽量使用较低的隔离级别
6. 尽量使用相同条件访问数据,这样可以避免间隙锁对并发的插入影响
7. 精心设计索引,尽量使用索引访问数据
8. 借助相关工具:pt-deadlock-logger

乐观锁与悲观锁

一张图彻底搞懂 MySQL 的锁机制

7.1 悲观锁

解释

假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作

实现机制

表锁、行锁等

实现层面

数据库本身

适用场景

并发量大

7.2 乐观锁

解释

假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性

实现机制

提交更新时检查版本号或者时间戳是否符合

实现层面

业务代码

适用场景

并发量小

更多相关免费学习推荐:mysql教程(视频)

以上是一起徹底搞懂 MySQL 的鎖機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:learnku。如有侵權,請聯絡admin@php.cn刪除
MySQL中的存儲過程是什麼?MySQL中的存儲過程是什麼?May 01, 2025 am 12:27 AM

存儲過程是MySQL中的預編譯SQL語句集合,用於提高性能和簡化複雜操作。 1.提高性能:首次編譯後,後續調用無需重新編譯。 2.提高安全性:通過權限控制限制數據表訪問。 3.簡化複雜操作:將多條SQL語句組合,簡化應用層邏輯。

查詢緩存如何在MySQL中工作?查詢緩存如何在MySQL中工作?May 01, 2025 am 12:26 AM

MySQL查詢緩存的工作原理是通過存儲SELECT查詢的結果,當相同查詢再次執行時,直接返回緩存結果。 1)查詢緩存提高數據庫讀取性能,通過哈希值查找緩存結果。 2)配置簡單,在MySQL配置文件中設置query_cache_type和query_cache_size。 3)使用SQL_NO_CACHE關鍵字可以禁用特定查詢的緩存。 4)在高頻更新環境中,查詢緩存可能導致性能瓶頸,需通過監控和調整參數優化使用。

與其他關係數據庫相比,使用MySQL的優點是什麼?與其他關係數據庫相比,使用MySQL的優點是什麼?May 01, 2025 am 12:18 AM

MySQL被廣泛應用於各種項目中的原因包括:1.高性能與可擴展性,支持多種存儲引擎;2.易於使用和維護,配置簡單且工具豐富;3.豐富的生態系統,吸引大量社區和第三方工具支持;4.跨平台支持,適用於多種操作系統。

您如何處理MySQL中的數據庫升級?您如何處理MySQL中的數據庫升級?Apr 30, 2025 am 12:28 AM

MySQL數據庫升級的步驟包括:1.備份數據庫,2.停止當前MySQL服務,3.安裝新版本MySQL,4.啟動新版本MySQL服務,5.恢復數據庫。升級過程需注意兼容性問題,並可使用高級工具如PerconaToolkit進行測試和優化。

您可以使用MySQL的不同備份策略是什麼?您可以使用MySQL的不同備份策略是什麼?Apr 30, 2025 am 12:28 AM

MySQL備份策略包括邏輯備份、物理備份、增量備份、基於復制的備份和雲備份。 1.邏輯備份使用mysqldump導出數據庫結構和數據,適合小型數據庫和版本遷移。 2.物理備份通過複製數據文件,速度快且全面,但需數據庫一致性。 3.增量備份利用二進制日誌記錄變化,適用於大型數據庫。 4.基於復制的備份通過從服務器備份,減少對生產系統的影響。 5.雲備份如AmazonRDS提供自動化解決方案,但成本和控制需考慮。選擇策略時應考慮數據庫大小、停機容忍度、恢復時間和恢復點目標。

什麼是mySQL聚類?什麼是mySQL聚類?Apr 30, 2025 am 12:28 AM

MySQLclusteringenhancesdatabaserobustnessandscalabilitybydistributingdataacrossmultiplenodes.ItusestheNDBenginefordatareplicationandfaulttolerance,ensuringhighavailability.Setupinvolvesconfiguringmanagement,data,andSQLnodes,withcarefulmonitoringandpe

如何優化數據庫架構設計以在MySQL中的性能?如何優化數據庫架構設計以在MySQL中的性能?Apr 30, 2025 am 12:27 AM

在MySQL中優化數據庫模式設計可通過以下步驟提升性能:1.索引優化:在常用查詢列上創建索引,平衡查詢和插入更新的開銷。 2.表結構優化:通過規範化或反規範化減少數據冗餘,提高訪問效率。 3.數據類型選擇:使用合適的數據類型,如INT替代VARCHAR,減少存儲空間。 4.分區和分錶:對於大數據量,使用分區和分錶分散數據,提升查詢和維護效率。

您如何優化MySQL性能?您如何優化MySQL性能?Apr 30, 2025 am 12:26 AM

tooptimizemysqlperformance,lofterTheSeSteps:1)inasemproperIndexingTospeedUpqueries,2)使用ExplaintplaintoAnalyzeandoptimizequeryPerformance,3)ActiveServerConfigurationStersLikeTlikeTlikeTlikeIkeLikeIkeIkeLikeIkeLikeIkeLikeIkeLikeNodb_buffer_pool_sizizeandmax_connections,4)

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。