1. 程式人生 > >技本功丨淺談MySQL的七種鎖

技本功丨淺談MySQL的七種鎖

fe8f973d4c9487651577a863493b1a6.png

作者:宋丹琪(花名:三思)袋鼠云云服務部DBA團隊 資料庫工程師

時常會有開發的同學突然緊張兮兮地找我,

然後丟給我一個程式碼層面的

CannotAcquireLockException的報錯,

一臉無辜地問我是不是自己搞出了一個死鎖。

微信圖片_201812061332411.png


好像大家看到LOCK的字眼

總會第一時間想到死鎖而忽略了鎖,

難道我們鎖沒有面子的嘛,

我們鎖的大家族可足足有七種呢?

那麼到底什麼是鎖,有哪些鎖,

請聽我娓娓道來。。

01 共享鎖(S鎖)和排它鎖(X鎖)

事務拿到某一行記錄的共享S鎖,才可以讀取這一行,並阻止別的事物對其新增X鎖

事務拿到某一行記錄的排它X鎖,才可以修改或者刪除這一行

共享鎖的目的是提高讀讀併發

排他鎖的目的是為了保證資料的一致性

02 意向鎖

1)意向共享鎖

預示事務有意向對錶中的某些行加共享S鎖

2)意向排他鎖

預示著事務有意向對錶中的某些行加排他X鎖

3) IS、S、IX、X鎖之間的相容性比較

微信圖片_201812061332412.png


4)意向鎖的意義在哪裡?

1.IX,IS是表級鎖,不會和行級的X,S鎖發生衝突。只會和表級的X,S發生衝突

2.意向鎖是在新增行鎖之前新增。

3.如果沒有意向鎖,當向一個表新增表級X鎖時,就需要遍歷整張表來判斷是否存行鎖,以免發生衝突

4.如果有了意向鎖,只需要判斷該意向鎖與表級鎖是否相容即可。

03 插入意向鎖(insert intention looks)

插入意向鎖是間隙鎖的一種,針對insert操作產生。

目的是提高插入併發。

多個事物,在同一個索引,同一個範圍區間進行插入記錄的時候,如果 插入的位置不衝突,不會阻塞彼此。

示例:

微信圖片_20181206133242.png


由於事物一和事物二都是對錶的同一索引範圍進行insert,使用的插入意向鎖,由於插入的記錄並不衝突,所以並不會阻塞事物二。如果事物二插入的記錄與事物一衝突,會被X鎖阻塞。

04 記錄鎖

對單條索引記錄進行加鎖,鎖住的是索引記錄而非記錄本身,即使表中沒有任何索引,MySQL會自動建立一個隱式的row_id作為聚集索引來進行加鎖。

微信圖片_201812061332421.png


05 間隙鎖(gap鎖)

封鎖記錄中的間隔,防止間隔中被其他事務插入。

間隙鎖主要出現在RR隔離級別,避免出現幻讀。

MVCC(多版本併發)

1.MVCC的作用

避免髒讀、寫不阻塞讀、實現可重複讀、多版本控制

2.在MVCC下,讀操作可以分為兩種:快照讀、當前讀

1)快照讀

select * from tbl_name where ...

2)當前讀

select * from tbl_name where ... for update;

update

delete

insert

3)為什麼delete/update也是一種當前讀?(如一個update操作)

a.在進行update的時候,MySQL會根據where條件得到過濾出來的第一條記錄,並進行加鎖(currenet read)

b.對該條記錄進行update

c.再次讀取下一條記錄,直到沒有滿足條件的記錄為止

d.delete原理與之類似

4)為什麼insert也是一種當前讀?

insert操作可能會觸發Unique Key的衝突檢查,也會進行一個當前讀。

隔離級別

1.Read Uncommitted

可以讀取到未提交的事物。

2.Rrad Committed(RC)

針對當前讀,RC隔離級別保證對讀取到的記錄加鎖 (記錄鎖),存在幻讀現象。

3.Repeatable Read (RR)

針對當前讀,RR隔離級別保證對讀取到的記錄加鎖 (記錄鎖),同時保證對讀取的範圍加鎖,新的滿足查詢條件的記錄不能夠插入 (間隙鎖),不存在幻讀現象。

4.Serializable

所有的讀操作均為當前讀,讀加讀鎖 (S鎖),寫加寫鎖 (X鎖)。

讀寫衝突,併發行很差。

幾種觸發間隙鎖的情況

1.id非唯一索引+RR

微信圖片_201812061332422.png


SQL:delete from t1 where id = 10;

加鎖流程如下:

a.通過id索引定位到第一條滿足查詢條件的記錄,加記錄上的X鎖,加GAP上的GAP鎖,

b.然後加主鍵聚簇索引上的記錄X鎖,然後返回;

c.然後讀取下一條,重複進行。

d.直至進行到第一條不滿足條件的記錄[11,f],此時,不需要加記錄X鎖,但是仍舊需要加GAP鎖,最後返回結束。

2.id無索引+RR

微信圖片_201812061332423.png


SQL:delete from t1 where id = 10;

a.由於id欄位無索引,進行全表掃描的當前讀,

b.聚簇索引上的所有記錄,都被加上了X鎖。其次,聚簇索引每條記錄間的間隙都被加上了GAP鎖。

3.針對id無索引+RR MySQL效能上做的一些優化

semi-consistent read

semi-consistent read開啟的情況下,對於不滿足查詢條件的記錄,MySQL會提前放鎖。

針對上面的這個用例,就是除了記錄[d,10],[g,10]之外,所有的記錄鎖都會被釋放,同時不加GAP鎖。

4.semi-consistent read如何觸發?

1)隔離級別是read committed;

2)隔離級別是Repeatable Read,同時設定了innodb_locks_unsafe_for_binlog 引數。

示例一

微信圖片_201812061332424.png


微信圖片_201812061332425.png


示例二

微信圖片_201812061332426.png


微信圖片_201812061332427.png


示例三

微信圖片_201812061332428.png


微信圖片_201812061332429.png


06 臨鍵鎖(Next-Key Locks)

臨鍵鎖是記錄鎖和間隙鎖的組合,既鎖住了記錄也鎖住了範圍。

臨鍵鎖的主要目的,也是為了避免幻讀。

如果把事務的隔離級別降級為RC,臨鍵鎖就也會失效。

通常情況下,InnoDB在搜尋或掃描索引的行鎖機制中使用“臨鍵鎖(next-key locking)”演算法來鎖定某索引記錄及其前部的間隙(gap),以阻塞其它使用者緊跟在該索引記錄之前插入其它索引記錄。

innodb_locks_unsafe_for_binlog預設為OFF,意為禁止使用非安全鎖,也即啟用間隙鎖功能。將其設定為ON表示禁止鎖定索引記錄前的間隙,也即禁用間隙鎖,InnoDB僅使用索引記錄鎖(index-record lock)進行索引搜尋或掃描,不過,這並不禁止InnoDB在執行外來鍵約束檢查或重複鍵檢查時使用間隙鎖。

innodb_locks_unsafe_for_binlog的效果:

(1)對UPDATE或DELETE語句來說,InnoDB僅鎖定需要更新或刪除的行,對不能夠被WHERE條件匹配的行施加的鎖會在條件檢查後予以釋放。這可以有效地降低死鎖出現的概率;

(2)執行UPDATE語句時,如果某行已經被其它語句鎖定,InnoDB會啟動一個“半一致性(semi-consistent)”讀操作從MySQL最近一次提交版本中獲得此行,並以之判定其是否能夠並當前UPDATE的WHERE條件所匹配。如果能夠匹配,MySQL會再次對其進行鎖定,而如果仍有其它鎖存在,則需要先等待它們退出。

(3)innodb_locks_unsafe_for_binlog可能會造成幻讀

示例一

innodb_locks_unsafe_for_binlog=off的情況下:

微信圖片_2018120613324210.png


微信圖片_2018120613324211.png


示例二

innodb_locks_unsafe_for_binlog=on的情況下:

微信圖片_2018120613324212.png


微信圖片_2018120613324213.png


檢視binlog日誌:

微信圖片_2018120613324214.png


因此,當innodb_locks_unsafe_for_binlog=on的情況下,會讓你容易造成資料的不一致。

07 自增長鎖

自增長鎖是一種表級鎖,專門針對auto_increment型別的列。

自增長列鎖各模式分析:

innodb_autoinc_lock_mode:自增長長鎖模式

0:

不管是insert into values (simple insert)還是insert into select (bulk insert),都是:持有鎖、讀取/修改、執行SQL、釋放,不需要等到事務提交就釋放鎖,但是需要SQL執行完成,並且不能保證連續。

持有latch ---> 讀取和修改auto鎖 ---> 執行insert ---> 釋放

注意:不需要等待insert所在的事務是否提交

缺點:可能出現數字不連續

持有時間相對過長:SQL執行完畢,不需要事務提交

1:

預設值,對於回滾是不能保證自增長列連續的。

對於simple insert (insert into values):持有鎖、讀取、釋放、執行SQL,最快,不需要執行完SQL就釋放,不需要等待insert執行完畢就可以釋放鎖。

對於bulk insert (insert into select):持有鎖、讀取、執行SQL、釋放,需要執行完SQL才釋放。(對於批量insert來說等同於0)

優點:

相關推薦

MySQL

作者:宋丹琪(花名:三思)袋鼠云云服務部DBA團隊 資料庫工程師 時常會有開發的同學突然緊張兮兮地找我, 然後丟給我一個程式碼層面的 CannotAcquireLockException的報錯, 一臉無辜地問我是不是自己搞出了一個死鎖。 好像大家看到LOCK的字眼 總會第一時間想到

請帶上紙筆刷著看:解讀MySQL執行計劃的type列和extra列

訪問表 column pri exp 證明 分享圖片 sele aca sel 本萌最近被一則新聞深受鼓舞,西工大硬核“女學神”白雨桐,獲6所世界頂級大學博士錄取 貨真價值的才貌雙全,別人家的孩子 高考失利與心儀的專業失之交臂,選擇了軟件工程

網際網路+工業視覺異常檢測分析

胡豐——袋鼠雲高階演算法專家 袋鼠雲人工智慧實驗室負責人。十年影象處理、模式識別、機器視覺等方面的研發工作,主要研究領域為:智慧交通、工業視覺分析、OCR、視訊智慧質量診斷、智慧球機跟蹤、人臉等方向,發表第一作者發明專利十餘篇、國際發明專利一篇。 我國工業網際網路已經形成“三條途徑”:一是打造智慧

騷操作:教你如何用一支菸的時間來寫個日誌採集工具

作者:良辰 袋鼠雲日誌團隊 後端開發工程師 我放下了手中的鍵盤,陷入沉思, 作為一個優秀的程式猿最重要的就是 氣~勢~ 泰山崩於前的鎮~定~   我用最快的速度掃描了一遍現行的 filebeat、fluentd、flume、 scribe等解決方案, 發

智慧監控,在袋鼠雲日誌運用中都經歷了什麼……

  作者:大鵬 袋鼠雲日誌團隊後端開發工程師 傳統監控範圍小,智慧監控效率高,你說到底怎麼用?大鵬給你來支招~ 傳統監控是通過對監控項設定一個固定值(閾值),當監控項指標超過這個閾值時就通知人們關注這個指標項。傳統監控一般適用於一定範圍波動的業務指標: 比如磁碟的使

一個等待現象的診斷案例

作者:蘇坡 袋鼠云云服務部-DBA團隊 資料庫工程師 前兩日與一個客戶交流,客戶提出了一些對mysql隔離級別以及鎖的疑問,然後問到了出現鎖等待現象的排查思路。這不禁讓我回想起,long long ago,做過的一個診斷案例。當年我還不是一枚老司機,折騰了兩三天才完全搞定,現在回想還頗有些借鑑價

web伺服器日誌自動解析工具不是唯一的工具,但卻承包了我最深沉的愛!

曾經有個web伺服器日誌自動解析工具擺在我面前,我沒有珍惜。等我失去的時候我才追悔莫及,人世間最痛苦的事莫過於此。 事情就是這樣發生的—— 當前web伺服器的多樣化使得訪問日誌的資料清洗變得越來越複雜,企業需要投入專業的資料清洗人員編寫資料清洗規則(解析規則或者解析正則),或者需要關心

來~與你講一段ES節點擴容、資料遷移的故事……

運維攻城獅 作為最優(ku)秀(bi)的職業 若是沒有些方法技巧 那是極可能需要犧牲些個人時間 對此,本萌我 不能視而不見,見而不救啊! 比如,ES叢集裡的資料越來越大, 日增500G日誌資料, 日誌數量太多怎麼辦? 來來來,掌聲有請 幫你做一波擴容,讓你走上人生巔峰!

甲方大人來了之運維資料分析平臺搭建實戰

袋鼠雲日誌團隊時常遇到各種各樣的甲方大人,畢竟我們是一個非常優秀的企業服務公司(自信滿滿),當然面對甲方大人的時候要做到處變不驚,臨危不亂,鎮定自若的接受需求…… 甲方大人的常用臺詞一定要記住:我們很忙,有好幾套監控系統,能不能再不砍掉監控系統的情況下,幫助我們搞定日運維需求呢?這樣的需求每

呀~我不會寫CSS之vertical-align(上集)

某日閱讀《CSS世界》,筆者的一段話鞭撻了我的靈魂。原文是這樣的—— “說到這裡,我就忍不住多說兩句。很多其實工作很多年的前端開發人員,也可能不知道vertical-align的屬性值支援數值,更不知道支援負值,這著實讓我很意外“。 ...... 羞愧啊,滿滿的羞愧啊!本人便是那類前

create-react-app升級webpack4填坑

都說create-react-app是業界最優秀的 React 應用開發工具之一。But,webpack4都更新到v4.20.2 它居然~還沒升級,簡直~不能忍 看到webpack這更新速度,本人慌得一批,剛好抽空搭建react-andt-mobx腳手架準備升級~ So,

用短平快的方式告訴你:Flink-SQL的擴展實現

mps flink 加載 ast 正則表達 快的 網絡 叠代 參數 2019年1月28日,阿裏雲宣布開源“計算王牌”實時計算平臺Blink回饋給ApacheFlink社區。官方稱,計算延遲已經降到毫秒級,也就是你在瀏覽網頁的時候,眨了一下眼睛,淘寶、

MYSQL之日誌文件系統

mysql日誌文件系統 同大多數關系型數據庫一樣,日誌文件是MySQL數據庫的重要組成部分。MySQL有幾種不同的日誌文件,通常包括錯誤日誌文件,二進制日誌,通用日誌,慢查詢日誌,等等。這些日誌可以幫助我們定位mysqld內部發生的事件,數據庫性能故障,記錄數據的變更歷史,用戶恢復數據庫等等 MySQL

Linux的文處理工具-awk sed grep

line 二進制 in use react 過程 reac otl split === Linux的文本處理工具淺談 awk 老大 【功能說明】 用於文本處理的語言(取行,過濾),支持正則 NR代表行數,$n取某一列,$NF最後一列 NR==20,NR

Mysql中where和having的區別

where和having的區別一、誤區:不要錯誤的認為having和group by 必須配合使用.二、where和having用法解析:1、 where和having都可以使用的場景: select goods_price,goods_name from goods where goods_price &g

MySQL存儲引擎-InnoDB&MyISAM

SM 形式 負責 技術 兩個 insert tab mysql存儲 alt 存儲引擎在MySQL的邏輯架構中位於第三層,負責MySQL中的數據的存儲和提取。MySQL存儲引擎有很多,不同的存儲引擎保存數據和索引的方式是不同的。每一種存儲引擎都有它的優勢和劣勢,本文只討論最常

MySQL中優化sql語句查詢常用的30方法

系統資源 all 數據量過大 連續 don 問題 not sele 客戶端 1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用

Mysql數據庫的備份方案

all data dmi 51cto 刪除 redo 關於 skip date 自從入行幹IT互聯網已經有些年頭了,以前自己確實比較懶,從來不寫博文,從來不總結工作經驗,導致自身的技術提升的很慢,成長也是很慢,正兒八經的開始寫博文也是從去年才開始的,寫點東西,總結下,確實挺

MySQL引擎

mem mys 隨機 spa 也有 pan 很多 總結 簡單 MySQL有很多引擎,MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED...等等 比較常用的就是InnoDB和MyISAM了 &

OSI層模型

表現 以及 數據鏈路層 網絡服務 介質 包裝 斷點續傳 pop3 ip地址 OSI是由ISO(國際標準化組織)在網絡通信中創建的開放系統互聯模型,為降低網絡設計的復雜性將協議進行了分層設計。一、OSI七層模型的含義 OSI結構 含義 應用層 網絡服務於最終用戶