show variables like '%storage_engine%';
深入了解Mysql中的鎖,聊聊使用場景吧!
這篇文章帶大家了解一下Mysql中的鎖,搞懂共享鎖、排他鎖、悲觀鎖、樂觀鎖,並聊聊使用場景,希望對大家有幫助!
一、常見鎖定類型
- #表格層級鎖定,鎖定整個表格
- #頁級鎖,鎖定一頁
- 行級鎖,鎖定一行
- 共享鎖,也叫S鎖,在MyISAM中也叫讀鎖
- 排他鎖,也叫X鎖,在MyISAM中也叫寫鎖
- 悲觀鎖,抽象性質,其實不真實存在
- 樂觀鎖,抽象性質,其實不真實存在

#二、Mysql引擎介紹
- 其實mysql中的引擎有很多種類,其中InnoDB和MyISAM引擎最常使用
- 在mysql5.5版本前預設使用MyISAM引擎,之後使用InnoDB引擎
show variables like '%storage_engine%';
登入後複製
三、常用引擎間的區別 show variables like '%storage_engine%';
- #MyISAM 操作資料都是使用的表鎖,你更新一筆記錄就要鎖整個表,導致性能較低,併發不高。當然同時它也不會有死鎖問題。
- 而 InnoDB 與 MyISAM 的最大差異有兩點:一是 InnoDB 支援交易;二是 InnoDB 採用了行級鎖定。
- 在 Mysql 中,行級鎖定並不是直接鎖定記錄,而是鎖定索引。索引分為主鍵索引和非主鍵索引兩種,如果一條sql 語句操作了主鍵索引,Mysql 就會鎖定這條主鍵索引;如果一語句操作了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相關的主鍵索引。
- InnoDB 行鎖定是透過在索引項目上加鎖定來實現的,如果沒有索引,InnoDB 會透過隱藏的叢集索引來對記錄加鎖。也就是說:如果不透過索引條件檢索數據,那麼InnoDB將對錶中所有數據加鎖,實際效果跟表鎖一樣。因為沒有了索引,找到某一筆記錄就得掃描全表,要掃描全表,就得鎖定表。
四、共享鎖與排他鎖
- #資料庫的增刪改操作預設都會加排他鎖,而查詢不會加任何鎖。
-
共享鎖:
對某一資源加上共享鎖,自己可以讀該資源,其他人也可以讀該資源(也可以再繼續加共享鎖,即共享鎖可多個共存),但無法修改。要修改就必須等所有共享鎖都釋放完之後。 -
排他鎖:###對某一資源加排他鎖,自身可以進行增刪改查,其他人無法進行任何操作。 ###
//共享锁 select * from 表名 lock in share mode //排他锁 select * from 表名 for update
五、排他锁的实际应用
- 这里我们以两个操作数据库的请求为例,假设这两个请求分别为T1和T2
- 假设T1为查询请求,而T2为更新数据请求,在T1查询很长时间的时候,还没有返回结果,但是这时候T2过来请求更新了
- 这个流程应该是: T1运行加共享锁、T2运行、发现T1未完成等待其完成、T1完成、T2开始执行
- T2之所以要等待,是因为T2执行更新的时候需要给表加排他锁,但是数据库规定,不能在同一资源上同时共存这两种锁,所以T2必须等T1执行完,释放锁后,才可以正常操作
T1: select * from 表名 lock in share mode //假设还未返回结果 T2: update 表名 set name='autofelix'
六、共享锁的实际应用
- 如果T1和T2都是执行的查询,也就是都加共享锁
- 这时候就不用等待,可以立马执行
- 因为同一资源上可以同时存在多个共享锁,也被称为,共享锁与共享锁兼容
- 意味着共享锁不阻止其他人同时读取资源,但是阻止其他人修改资源
T1: select * from table lock in share mode T2: select * from table lock in share mode
七、死锁的发生
- 假设T1和T2都同时执行2个资源操作,分别是查询和更新数据
- 假设T1和T2同时达到select,T1对表加共享锁,而T2也加上了共享锁
- 当T1的select执行完毕,准备执行update时
- 根据锁机制,T1的共享锁必须升级到排他锁才可以执行接下来的update操作
- 在升级排他锁之前,必须等T2的共享锁释放,同理,T2也在等T1的共享锁释放
- 于是都在等待对方的锁释放,导致程序卡死,这种情况就是死锁
T1: 开启事务,执行查询更新两个操作 select * from table lock in share mode update table set column1='hello' T2: 开启事务,执行查询更新两个操作 select * from table lock in share mode update table set column1='world'
八、另一种发生死锁的情景
- 当T1和T2都是只执行更新语句的时候
- 如下程序所示,这种语句非常的常见,很多人觉得他会产生死锁,其实要看情况
- 如果id是主键,由于主键机制,并不需要全表扫描,直接可以更新当前数据,所以不会产生死锁
- 如果id是普通字段,那么当T1加上排他锁之后,T2为了找到id=20条数据,必须进行全表扫描,当他扫到第10条的时候,发现这里有排他锁,导致全表扫描进行不下去,就会导致等待
T1: begin update table set content='hello' where id=10 T2: begin update table set content='world' where id=20
九、死锁的解决方式
- 就是让T1和T2顺序执行,比如T1在执行完select后,立马给自身加上排他锁,这样T2不得不等待T1执行完才能继续
- 但是如果有很多请求过来的话,都必须等待,这对用户特别的不友好
- 所以,某些数据库引入了另一种方式,叫做更新锁,这里mysql除外,不存在更新锁
- 更新锁其实就是排他锁的另一种实现,只是他允许其他人读的同时加共享锁,但是不允许其他操作,除非释放了更新锁
- 流程大概如此: T1执行完select加上更新锁,T2执行查询完,准备加更新锁,发现已经有了,就等待,其他请求过来,如果查询是不受影响的,但是更新才等待
- 这相比上面的查询也要等待增加了效率
T1: begin select * from table for update update table set content='hello' T2: begin select * from table for update update table set content='world'
T1: begin select * from table [加更新锁操作] update table set content='hello' T2: begin select * from table [加更新锁操作] update table set content='world'
十、意向锁和计划锁
- 计划锁与程序猿无关,不需要了解
- 意向锁,Innodb特有,分为意向共享锁和意向排他锁
- 意向共享锁: 表示事务获取共享锁时,必须先得获取该表的意向共享锁
- 意向排他锁: 表示事务获取排他锁时,必须先得获取该表的意向排他锁
- 我们知道要对整个表加锁,必须保证表内不存在任何锁
- 如果一行行的去检查是否加锁,效率必然极低,这时候可以检测意向锁是否被占用即可
十一、乐观锁和悲观锁
- 乐观锁和悲观锁都是针对select而言的
- 比如在商品抢购中,用户购买后库存需要减1,而很多用户同时购买时,读出来的库存数量一样,然后多个用户同时用该库存去减1
- 这种做法必然会出现很大的漏洞,如果向在淘宝,京东出现这种情况,你就可以打包回家种地了
- 这种情况如何解决呢,其实可以使用悲观锁进行解决,说白了也就是排他锁
- 用户进来查库存的时候,就加上排他锁,等他所有操作完成后,再释放排他锁,让其他人进来
- 不让用户等待,就可以使用乐观锁方式解决,乐观锁一般靠表的设计和时间戳来实现
- 一般是在表中添加version或者timestamp时间戳字段
- 这样就会保证如果更新失败,就表示有其他程序更新了数据库,就可以通过重试解决
update table set num=num-1 where id=10 and version=12
【相关推荐:mysql视频教程】
以上是深入了解Mysql中的鎖,聊聊使用場景吧!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Laravel 是一款 PHP 框架,用於輕鬆構建 Web 應用程序。它提供一系列強大的功能,包括:安裝: 使用 Composer 全局安裝 Laravel CLI,並在項目目錄中創建應用程序。路由: 在 routes/web.php 中定義 URL 和處理函數之間的關係。視圖: 在 resources/views 中創建視圖以呈現應用程序的界面。數據庫集成: 提供與 MySQL 等數據庫的開箱即用集成,並使用遷移來創建和修改表。模型和控制器: 模型表示數據庫實體,控制器處理 HTTP 請求。

MySQL和phpMyAdmin是強大的數據庫管理工具。 1)MySQL用於創建數據庫和表、執行DML和SQL查詢。 2)phpMyAdmin提供直觀界面進行數據庫管理、表結構管理、數據操作和用戶權限管理。

MySQL与其他编程语言相比,主要用于存储和管理数据,而其他语言如Python、Java、C 则用于逻辑处理和应用开发。MySQL以其高性能、可扩展性和跨平台支持著称,适合数据管理需求,而其他语言在各自领域如数据分析、企业应用和系统编程中各有优势。

在開發一個小型應用時,我遇到了一個棘手的問題:需要快速集成一個輕量級的數據庫操作庫。嘗試了多個庫後,我發現它們要么功能過多,要么兼容性不佳。最終,我找到了minii/db,這是一個基於Yii2的簡化版本,完美地解決了我的問題。

文章摘要:本文提供了詳細分步說明,指導讀者如何輕鬆安裝 Laravel 框架。 Laravel 是一個功能強大的 PHP 框架,它 упростил 和加快了 web 應用程序的開發過程。本教程涵蓋了從系統要求到配置數據庫和設置路由等各個方面的安裝過程。通過遵循這些步驟,讀者可以快速高效地為他們的 Laravel 項目打下堅實的基礎。

在使用Thelia開發電商網站時,我遇到了一個棘手的問題:MySQL模式設置不當,導致某些功能無法正常運行。經過一番探索,我找到了一個名為TheliaMySQLModesChecker的模塊,它能夠自動修復Thelia所需的MySQL模式,徹底解決了我的困擾。

MySQL通過表結構和SQL查詢高效管理結構化數據,並通過外鍵實現表間關係。 1.創建表時定義數據格式和類型。 2.使用外鍵建立表間關係。 3.通過索引和查詢優化提高性能。 4.定期備份和監控數據庫確保數據安全和性能優化。

MySQL是一個開源的關係型數據庫管理系統,廣泛應用於Web開發。它的關鍵特性包括:1.支持多種存儲引擎,如InnoDB和MyISAM,適用於不同場景;2.提供主從復制功能,利於負載均衡和數據備份;3.通過查詢優化和索引使用提高查詢效率。
