日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

讀鎖寫鎖意向鎖,表鎖行鎖頁面鎖。

在學習JAVA并發編程的時候,肯定少不了學習。最常見的就是synchronized,鎖的概念不是很好理解,有的地方說是鎖住了一段代碼,有的地方說是鎖住了一個對象。弄得初學者都是丈二和尚——摸不著頭腦。

拋開這些結論性的說法,說一下我對鎖的理解(不管是Java中的鎖還是數據庫中的鎖,還是分布式鎖)。當我們需要限制某段程序在同一時刻,最多能被1個線程同時執行的時候就需要鎖。這個幸運的線程怎么選出來呢?那就讓他們去搶一個許可證吧,重點是需要保證這個許可證是唯一的,一次最多只能被一個線程搶到。許可證不要拘泥于是this,還有可能是數據庫設置了唯一鍵的列、緩存中唯一的key或者一個文件目錄。只有搶到了這個許可證的線程,才可以執行這段代碼,執行完成或者異常退出后自動釋放許可證

理解了這點,再說鎖住的是一段代碼、一個對象,甚至是一個線程都無所謂了,因為鎖的作用就是在某一段時間內將一段代碼、一個對象(許可證)、一個線程綁定在一起。

MySQL中的鎖與存儲引擎有關,MyISAM只支持表級鎖,InnoDB既支持表級鎖,又支持行級鎖

強人“鎖”難,MySQL到底有多少鎖?

 

InnoDB中的鎖

InnoDB實現了行級鎖,可以分為兩種類型:共享(S)鎖定和排他(X)鎖定。

  • 共享(S)鎖允許持有該鎖的事務讀取一行,所有又叫讀鎖
  • 排他(X)鎖允許持有該鎖的事務更新或刪除行,所以又叫寫鎖

多個事務并發執行時,如果事務T1在某一行r上持有共享(S)鎖,那么事務T2的對這行r的鎖請求將按以下方式處理:

  • T2對S鎖的請求可以立即獲得批準。T1和T2都在r上保持了S鎖
  • T2對X鎖的請求不能獲取批準。

如果事務T1在某一行r上擁有排他(X)鎖,則事務T2不能獲取鎖(不論是S鎖還是X鎖

換言之,S鎖和S鎖是兼容的,S鎖和X鎖是沖突的,X鎖和X鎖是沖突的

強人“鎖”難,MySQL到底有多少鎖?

 

但是共享鎖排它鎖并不是指具體的兩種鎖,而是指兩類鎖。
同樣的樂觀鎖悲觀鎖也不是指具體的鎖,而是指兩類鎖。樂觀鎖是樂觀的認為每次都不會發生沖突,只會在更新的時候檢查要更新的值有沒有被別人修改過,因為沒有加鎖,所以樂觀鎖又叫無鎖。在數據庫中一般是用MVCC實現樂觀鎖,在Java中用CAS實現樂觀鎖。至于悲觀鎖就是悲觀的認為每次都會發生沖突,所以每次修改都需要加鎖。

表鎖

表鎖是MySQL中粒度最大的一種鎖,簡單粗暴的鎖住整張表,實現簡單所以支持的并發度低。InnoDB和MyIASM都支持表鎖,表鎖分為共享(S)鎖排他(X)鎖
表鎖的特點是實現簡單,并發度低。加鎖快,開銷小。不會出現死鎖。

行鎖

行鎖是MySQL中粒度最細的一種鎖,每次只鎖住要操作的那一行。實現復雜,支持的并發度高。只有InnoDB支持行鎖。行鎖也分為共享(S)鎖排他(X)鎖。行鎖是對索引的鎖定。例如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE,防止任何其他事務插入,更新或刪除t.c1值為10的行。行鎖始終鎖定索引,對于沒有創建索引的表,InnoDB創建一個隱藏的聚簇索引并將該索引用于行鎖。
行鎖的特點是實現復雜,并發度高。加鎖慢,開銷大。會出現死鎖。

意向鎖(Intention Locks)

InnoDB支持多種粒度鎖定,允許行鎖表鎖并存。為了使在多個粒度級別上的鎖定變得切實可行,InnoDB實現了意圖鎖意向鎖是表級鎖,表示事務稍后對表中的行需要上哪種類型的鎖(共享鎖排他鎖)。有兩種類型的意圖鎖:
意向共享鎖(IS)表示事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的 IS 鎖。
意向排他鎖(IX)表示事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的 IX 鎖。

SELECT ... LOCK IN SHARE MODE設置IS鎖定,而SELECT ... FOR UPDATE設置IX鎖定

表級鎖之間的兼容性如下

強人“鎖”難,MySQL到底有多少鎖?

 

有的同學一看到這么多種情況就頭暈,死記硬背是不可能死記硬背的,這輩子都不會死記硬背。既然這樣,那就干脆不記,花點時間深入了解一下為什么要設計成表中這樣。

要想理解這個表,首先得理解為什么要有意向鎖(Intention Locks),關于意向鎖的作用,官方文檔上給出了這么一句話:

Intention locks do not block anything except full table requests (for example, LOCK TABLES … WRITE). The main purpose of intention locks is to show that someone is locking a row, or going to lock a row in the table.

意向鎖不會阻止任何其他請求,除了(鎖定)全表請求(例如LOCK TABLES ... WRITE)外。意向鎖定的主要目的是:聲明已經有事務正在鎖定表中的行,或者即將鎖定表中的行。

這句話透露出了意向鎖雖然是表鎖,但是和行鎖是完全兼容的(包括共享鎖排它鎖)。但是聲明表中的行正在被鎖定或者即將被鎖定,有什么用呢?

假設事務A給表中某一行加了排它鎖,而事務B想給這個表加一個全表的排他鎖,這時候事務B就需要判斷當前表中到底有沒有排他鎖,如果有的話,是不能成功加上去表的排它鎖的。此時,如果沒有意向鎖,事務B只能遍歷整個索引去判斷,這樣無疑是低效的。為了解決這個問題,MySQL引入了意向鎖。當事務A給某一行加了排它鎖或者共享鎖后,會分別在表上加意向排它鎖(IX)或者意向共享鎖(IS),這時,事務B就可很輕松的判斷當前表是否有行鎖,這也就是前文所說的:為了使在多個粒度級別上的鎖定變得切實可行,InnoDB實現了意圖鎖

理解了意圖鎖的作用,再來看看上面的表格。S鎖和X鎖之間的兼容性前文已經理清了,還剩下IX和IS之間以及S/X和IS/IX的兼容性。

由于某一行被加了S鎖或者X鎖后,表上都會加上對應的IS鎖和IX鎖。另一個事務想鎖住另一條記錄,也得加上對應的IS鎖或者IX鎖,所以IS和IS、IS和IX以及IX和IX必定是兼容的,不然整個表最多只能上一個行鎖。

至于S鎖、X鎖和IS鎖、IX鎖的兼容性則需與分情況討論了。當整個表上了X鎖之后,再也不能上別的X鎖或者S鎖了,所以X鎖和IS、IX都是沖突的。當整個表上了S鎖之后,不能再上X鎖了,但是還可以上S鎖,所以S鎖和IX鎖是沖突的,但是和IS鎖是兼容的。

這樣理解了之后,再看上面的那個表格,似乎也變得有規律了。

間隙鎖(Gap Locks)

間隙鎖鎖定的是索引記錄之間的間隙,或者在第一個或最后一個索引記錄之前的間隙。例如SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE,可以防止其他事務將t.c1為15的記錄插入表中,因為這兩個值之間的間隙是被鎖定的。
間隙可能跨越單個索引值,多個索引值,甚至為空。
間隙鎖的唯一目的是防止其他事務在間隙中插入數據。間隙鎖可以共存。一個事務執行的間隙鎖,不會阻止另一事務對相同的間隙進行間隙鎖定。

Next-Key Locks

Next-Key Locks是索引記錄上的行鎖索引記錄之前的間隙上的間隙鎖的組合。如果一個session在索引中的記錄R上具有共享排他鎖,則另一session不能按照索引順序在R之前的間隙中插入新的索引記錄。
默認情況下,InnoDB設置的事務隔離級別是REPEATABLE READ。在這種情況下,InnoDB使用Next-Key Locks進行搜索和索引掃描,這可以防止幻讀(虛讀)。關于MySQL隔離級別相關的問題,請參考:面試官:MySQL事務是怎么實現的

插入意圖鎖(Insert Intention Locks)

插入意圖鎖是在行插入之前,通過INSERT操作設置的間隙鎖的一種類型。如果多個事務想要在同一個間隙中插入不同的值(也就是插入的位置不同),則這多個事務均不會被阻塞。假設有索引記錄,其值分別為4和7。單獨的事務分別嘗試插入值5和6,在獲得插入行的排他鎖之前,每個事務都使用插入意圖鎖來鎖定4和7之間的間隙,但不會互相阻塞,因為插入的行是無沖突的。

自增鎖(AUTO-INC Locks)

AUTO-INC鎖是一種特殊的表級鎖,由事務插入具有AUTO_INCREMENT列的表中獲得。在最簡單的情況下,如果一個事務正在向表中插入值,則任何其他事務都必須等待這個事務在該表中進行插入,以便第一個事務插入的行接收連續的主鍵值。

MyISAM中的鎖

相比之下MyISAM中的鎖就簡單多了,因為MyISAM只支持表鎖。并且共享鎖排它鎖也滿足如下關系

強人“鎖”難,MySQL到底有多少鎖?

 

死鎖

前文提到InnoDB行鎖可能是出現死鎖,死鎖是一個計算機領域的概念,而不是數據庫特有的,所以死鎖的概念是通用的。這里演示下MySQL行鎖導致的死鎖,這也是官網上給出的例子
首先準備數據

## 創建表
CREATE TABLE t (i INT) ENGINE = InnoDB;
## 新增數據INSERT INTO t (i) VALUES(1);

具體操作的時間線如下

強人“鎖”難,MySQL到底有多少鎖?

 

事務A在T5執行時,事務B會收到一條錯誤信息

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

此處發生死鎖,因為事務A需要X鎖才能刪除該行。但是,不能授予該鎖定請求,因為事務B已經具有X鎖定請求,并且正在等待事務A釋放其S鎖定。由于B事先要求X鎖,因此A持有的S鎖也不能升級為X鎖。結果,InnoDB為其中一個客戶端生成一個錯誤并釋放其鎖。此時時,可以授予對另一個客戶端的鎖定請求,并從表中刪除該行。

也就是說MySQL可以自動檢測死鎖,并且放棄一個事務來成全另一個事務,這點與Java程序中的死鎖不一樣。

查詢事務、鎖相關的參考命令如下:

## 查看當前事務狀態
select trx_id, trx_state, trx_started, trx_requested_lock_id, trx_wait_started, trx_query, trx_isolation_level from information_schema.innodb_trx;
## 查看當前鎖定的事務select * from information_schema.innodb_locks;
## 查看當前正在等待鎖的事務select * from information_schema.innodb_lock_waits;

總結

鎖是MySQL非常重要的一個部分,雖然一般情況下鎖的鎖定和釋放都由MySQL自動完成。但是了解MySQL中的鎖還是很有必要,它讓我們進一步的了解了MySQL是如何處理并發的。

作者:Sicimike

原文鏈接:https://blog.csdn.net/Baisitao_/article/details/104829887

分享到:
標簽:MySQL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定