自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL鎖會不會,你就差看一看咯

數(shù)據(jù)庫 MySQL
本文章向大家介紹MySQL鎖詳細(xì)講解,包括數(shù)據(jù)庫鎖基本知識、表鎖、表讀鎖、表寫鎖、行鎖、MVCC、事務(wù)的隔離級別、悲觀鎖、樂觀鎖、間隙鎖GAP、死鎖等等,需要的朋友可以參考一下。

 [[282394]]

本文章向大家介紹MySQL鎖詳細(xì)講解,包括數(shù)據(jù)庫鎖基本知識、表鎖、表讀鎖、表寫鎖、行鎖、MVCC、事務(wù)的隔離級別、悲觀鎖、樂觀鎖、間隙鎖GAP、死鎖等等,需要的朋友可以參考一下。

 

MySQL鎖會不會,你就差看一看咯

 

數(shù)據(jù)庫鎖知識

不少人在開發(fā)的時候,應(yīng)該很少會注意到這些鎖的問題,也很少會給程序加鎖(除了庫存這些對數(shù)量準(zhǔn)確性要求極高的情況下),即使我們不會這些鎖知識,我們的程序在一般情況下還是可以跑得好好的。因為這些鎖數(shù)據(jù)庫隱式幫我們加了,只會在某些特定的場景下才需要手動加鎖。

對于UPDATE、DELETE、INSERT語句,InnoDB會自動給涉及數(shù)據(jù)集加排他鎖(X) MyISAM在執(zhí)行查詢語句SELECT前,會自動給涉及的所有表加讀鎖,在執(zhí)行增、刪、改操作前,會自動給涉及的表加寫鎖,這個過程并不需要用戶干預(yù)

表鎖

首先,從鎖的粒度,我們可以分成兩大類:

表鎖 :開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定力度大,發(fā)生鎖沖突概率高,并發(fā)度最低

行鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度小,發(fā)生鎖沖突的概率低,并發(fā)度高 不同的存儲引擎支持的鎖粒度是不一樣的==:InnoDB行鎖和表鎖都支持、MyISAM只支持表鎖!InnoDB只有通過索引條件檢索數(shù)據(jù)才使用行級鎖==,否則,InnoDB使用表鎖也就是說,InnoDB的行鎖是基于索引的!

表鎖下又分為兩種模式: 表讀鎖(Table Read Lock)&& 表寫鎖(Table Write Lock)

從下圖可以清晰看到,在表讀鎖和表寫鎖的環(huán)境下:讀讀不阻塞,讀寫阻塞,寫寫阻塞! 讀讀不阻塞:當(dāng)前用戶在讀數(shù)據(jù),其他的用戶也在讀數(shù)據(jù),不會加鎖 讀寫阻塞:當(dāng)前用戶在讀數(shù)據(jù),其他的用戶不能修改當(dāng)前用戶讀的數(shù)據(jù),會加鎖! 寫寫阻塞:當(dāng)前用戶在修改數(shù)據(jù),其他的用戶不能修改當(dāng)前用戶正在修改的數(shù)據(jù),會加鎖!

 

MySQL鎖會不會,你就差看一看咯

 

從上面已經(jīng)看到了:讀鎖和寫鎖是互斥的,讀寫操作是串行。

  • 如果某個進(jìn)程想要獲取讀鎖,同時另外一個進(jìn)程想要獲取寫鎖。在mysql中,寫鎖是優(yōu)先于讀鎖的!
  • 寫鎖和讀鎖優(yōu)先級的問題是可以通過參數(shù)調(diào)節(jié)的:max_write_lock_count和low-priority-updates

注:

 

MySQL鎖會不會,你就差看一看咯

 

行鎖

InnoDB和MyISAM有兩個本質(zhì)的區(qū)別:InnoDB支持行鎖、InnoDB支持事務(wù)

InnoDB實現(xiàn)了以下兩種類型的行鎖:

  • 共享鎖(S鎖、讀鎖):允許一個事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖。即多個客戶可以同時讀取同一個資源,但不允許其他客戶修改。
  • 排他鎖(X鎖、寫鎖):允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)取得相同數(shù)據(jù)集的讀鎖和寫鎖。寫鎖是排他的,寫鎖會阻塞其他的寫鎖和讀鎖。

另外,為了允許行鎖和表鎖共存,實現(xiàn)多粒度鎖機(jī)制,InnoDB還有兩種內(nèi)部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖:

  • 意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖,事務(wù)在給一個數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖。
  • 意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖。
  • 意向鎖也是數(shù)據(jù)庫隱式幫我們做了,不需要程序員關(guān)心!

MVCC

MVCC(Multi-Version ConcurrencyControl)多版本并發(fā)控制,可以簡單地認(rèn)為:MVCC就是行級鎖的一個變種(升級版)。在表鎖中我們讀寫是阻塞的,基于提升并發(fā)性能的考慮,MVCC一般讀寫是不阻塞的(很多情況下避免了加鎖的操作)。

可以簡單的理解為:對數(shù)據(jù)庫的任何修改的提交都不會直接覆蓋之前的數(shù)據(jù),而是產(chǎn)生一個新的版本與老版本共存,使得讀取時可以完全不加鎖。

事務(wù)的隔離級別

事務(wù)的隔離級別就是通過鎖的機(jī)制來實現(xiàn),鎖的應(yīng)用最終導(dǎo)致不同事務(wù)的隔離級別,只不過隱藏了加鎖細(xì)節(jié),事務(wù)的隔離級別有4種:

  • Read uncommitted:會出現(xiàn)臟讀,不可重復(fù)讀,幻讀
  • Read committed:會出現(xiàn)不可重復(fù)讀,幻讀
  • Repeatable read:會出現(xiàn)幻讀(Mysql默認(rèn)的隔離級別,但是Repeatable read配合gap鎖不會出現(xiàn)幻讀!)
  • Serializable:串行,避免以上的情況

Read uncommitted: 出現(xiàn)的現(xiàn)象--->臟讀:一個事務(wù)讀取到另外一個事務(wù)未提交的數(shù)據(jù),例子:A向B轉(zhuǎn)賬,A執(zhí)行了轉(zhuǎn)賬語句,但A還沒有提交事務(wù),B讀取數(shù)據(jù),發(fā)現(xiàn)自己賬戶錢變多了!B跟A說,我已經(jīng)收到錢了。A回滾事務(wù)【rollback】,等B再查看賬戶的錢時,發(fā)現(xiàn)錢并沒有多...

Read committed: 出現(xiàn)的現(xiàn)象--->不可重復(fù)讀:一個事務(wù)讀取到另外一個事務(wù)已經(jīng)提交的數(shù)據(jù),也就是說一個事務(wù)可以看到其他事務(wù)所做的修改,例如:A查詢數(shù)據(jù)庫得到數(shù)據(jù),B去修改數(shù)據(jù)庫的數(shù)據(jù),導(dǎo)致A多次查詢數(shù)據(jù)庫的結(jié)果都不一樣【危害:A每次查詢的結(jié)果都是受B的影響的,那么A查詢出來的信息就沒有意思了】

Repeatable read: 避免不可重復(fù)讀是事務(wù)級別的快照!每次讀取的都是當(dāng)前事務(wù)的版本,即使被修改了,也只會讀取當(dāng)前事務(wù)版本的數(shù)據(jù)

 

MySQL鎖會不會,你就差看一看咯

 

 

MySQL鎖會不會,你就差看一看咯

 

至于虛讀(幻讀):是指在一個事務(wù)內(nèi)讀取到了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后讀取不一致。和不可重復(fù)讀類似,但虛讀(幻讀)會讀到其他事務(wù)的插入的數(shù)據(jù),導(dǎo)致前后讀取不 一致,幻讀的重點在于新增或者刪除(數(shù)據(jù)條數(shù)變化),不可重復(fù)讀的重點是修改,幻讀和不可重復(fù)的區(qū)別?

樂觀鎖和悲觀鎖

無論是Read committed還是Repeatable read隔離級別,都是為了解決讀寫沖突的問題,現(xiàn)在考慮一個問題:有一張數(shù)據(jù)庫表USER,只有id、name字段,現(xiàn)在有2個請求同時操作表A,過程如下:(模擬更新丟失,雖然不是很恰當(dāng))

1. 操作1查詢出name="zhangsan"

2. 操作2也查詢出name="zhangsan"

3. 操作1把name字段數(shù)據(jù)修改成lisi并提交

4. 操作2把name字段數(shù)據(jù)修改為wangwu并提交

那么操作1的更新丟失啦,即一個事務(wù)的更新覆蓋了其它事務(wù)的更新結(jié)果,解決上述更新丟失的方式有如下3種:

  • 使用Serializable隔離級別,事務(wù)是串行執(zhí)行的!
  • 樂觀鎖
  • 悲觀鎖

悲觀鎖

我們使用悲觀鎖的話其實很簡單(手動加行鎖就行了):select * from xxxx for update,在select 語句后邊加了for update相當(dāng)于加了排它鎖(寫鎖),加了寫鎖以后,其他事務(wù)就不能對它修改了!需要等待當(dāng)前事務(wù)修改完之后才可以修改.也就是說,如果操作1使用select ... for update,操作2就無法對該條記錄修改了,即可避免更新丟失。

樂觀鎖

樂觀鎖不是數(shù)據(jù)庫層面上的鎖,需要用戶手動去加的鎖。一般我們在數(shù)據(jù)庫表中添加一個版本字段version來實現(xiàn),例如操作1和操作2在更新User表的時,執(zhí)行語句如下:

update A set Name=lisi,version=version+1 where ID=#{id} and version=#{version},

此時即可避免更新丟失。

間隙鎖GAP

當(dāng)我們用范圍條件檢索數(shù)據(jù)而不是相等條件檢索數(shù)據(jù),并請求共享或排他鎖時,InnoDB會給符合范圍條件的已有數(shù)據(jù)記錄的索引項加鎖;對于鍵值在條件范圍內(nèi)但并不存在 的記錄,叫做“間隙(GAP)”。InnoDB也會對這個“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖。例子:假如emp表中只有101條記錄,其empid的值分別是1,2,...,100,101

  1. Select * from emp where empid > 100 for update

上面是一個范圍查詢,InnoDB不僅會對符合條件的empid值為101的記錄加鎖,也會對empid大于101(這些記錄并不存在)的“間隙”加鎖

InnoDB使用間隙鎖的目的有2個:

  • 為了防止幻讀(上面也說了,Repeatable read隔離級別下再通過GAP鎖即可避免了幻讀)
  • 滿足恢復(fù)和復(fù)制的需要:MySQL的恢復(fù)機(jī)制要求在一個事務(wù)未提交前,其他并發(fā)事務(wù)不能插入滿足其鎖定條件的任何記錄,也就是不允許出現(xiàn)幻讀

死鎖

并發(fā)的問題就少不了死鎖,在MySQL中同樣會存在死鎖的問題

鎖總結(jié)

表鎖其實我們程序員是很少關(guān)心它的:

  • 在MyISAM存儲引擎中,當(dāng)執(zhí)行SQL語句的時候是自動加的。
  • 在InnoDB存儲引擎中,如果沒有使用索引,表鎖也是自動加的。

現(xiàn)在我們大多數(shù)使用MySQL都是使用InnoDB,InnoDB支持行鎖:

  • 共享鎖--讀鎖--S鎖
  • 排它鎖--寫鎖--X鎖

在默認(rèn)的情況下,select是不加任何行鎖的~事務(wù)可以通過以下語句顯示給記錄集加共享鎖或排他鎖。

  • 共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
  • 排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE

InnoDB基于行鎖還實現(xiàn)了MVCC多版本并發(fā)控制,MVCC在隔離級別下的Read committed和Repeatable read下工作。MVCC實現(xiàn)了讀寫不阻塞

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2010-01-27 13:54:52

IT電影

2020-03-06 09:00:31

微信看一看質(zhì)量

2021-05-28 11:30:39

物聯(lián)網(wǎng)互聯(lián)網(wǎng)IoT

2024-03-07 08:22:32

CSS變量代碼

2024-10-08 09:35:23

2018-03-16 10:07:30

霍金預(yù)言人工智能

2018-12-29 13:53:19

微信今日頭條

2020-02-14 08:00:00

WindowsLinuxSamba

2011-03-23 09:33:51

HTML 5

2018-03-08 11:10:33

分布式存儲Ceph

2009-05-19 10:18:00

機(jī)房網(wǎng)絡(luò)管理

2021-05-07 09:03:27

算法模型技術(shù)

2021-04-28 07:34:09

電腦軟件ArcTime

2021-05-22 07:27:14

程序員專業(yè)術(shù)語編程

2019-04-26 09:16:51

存儲

2010-03-30 11:27:03

臺式機(jī)無線網(wǎng)卡

2020-03-26 14:56:29

運營商薪酬員工

2011-02-22 17:55:08

Konqueror

2024-06-03 00:00:01

索引MySQL技術(shù)

2012-10-17 10:09:14

大數(shù)據(jù)大數(shù)據(jù)管理數(shù)據(jù)挖掘
點贊
收藏

51CTO技術(shù)棧公眾號