MySQL相關(七)- innodb 鎖的介紹及使用

前言

前面咱們經過查詢語句,更新語句瞭解了 MySQL 的 innodb 的內部結構以及執行的流程,以後咱們講了有關索引的內容,經過介紹 innodb 的邏輯存儲結構和 B+Tree的模型推演來引出索引的概念,並闡述了咱們如何經過咱們對索引的瞭解對 MySQL 進行性能優化;再到後面,咱們來到了事務的篇章,咱們分別講了事務的四大特性以及隔離級別,至於關於隔離級別的實現,咱們總共有兩種實現方案,LBCC 以及 MVCC,在上一篇章中,咱們着重講了 MVCC 的相關介紹,關於鎖的方面,咱們且看這一篇章。php

老規矩,先上飛機票:html

  1. MySQL相關(一)- 一條查詢語句是如何執行的
  2. MySQL相關(二)- 一條更新語句是如何執行的
  3. MySQL相關(番外篇)- innodb 邏輯存儲結構
  4. MySQL相關(三)- 索引數據模型推演及 B+Tree 的詳細介紹
  5. MySQL相關(四)- 性能優化關鍵點索引
  6. MySQL相關(五)- 事務特性及隔離級別的詳細介紹
  7. MySQL相關(六)- 事務隔離級別的實現方案(MVCC)

前面提到的腦圖以下,想要完整高清圖片能夠到微信個人公衆號下【6曦軒】下回復 MySQL 腦圖獲取: mysql

在這裏插入圖片描述

正文

MySQL InnoDB 鎖的基本類型

dev.mysql.com/doc/refman/…程序員

官網把鎖分紅了 8 類。因此咱們把前面的兩個行級別的鎖(Shared and Exclusive Locks),和兩個表級別的鎖(Intention Locks)稱爲鎖的基本模式。面試

後面三個 Record Locks、Gap Locks、Next-Key Locks,咱們把它們叫作鎖的算法,也就是分別在什麼狀況下鎖定什麼範圍。算法

鎖的粒度

咱們講到 InnoDB 裏面既有行級別的鎖,又有表級別的鎖,咱們先來分析一下這兩種鎖定粒度的一些差別。sql

表鎖,顧名思義,是鎖住一張表;行鎖就是鎖住表裏面的一行數據。鎖定粒度,表鎖確定是大於行鎖的。數據庫

  • 那麼加鎖效率,表鎖應該是大於行鎖仍是小於行鎖呢?

大於。
爲何?
表鎖只須要直接鎖住這張表就好了,而行鎖,還須要在表裏面去檢索這一行數據,因此表鎖的加鎖效率更高。性能優化

  • 第二個衝突的機率?表鎖的衝突機率比行鎖大,仍是小?

大於,由於當咱們鎖住一張表的時候,其餘任何一個事務都不能操做這張表。可是咱們鎖住了表裏面的一行數據的時候,其餘的事務還能夠來操做表裏面的其餘沒有被鎖定的行,因此表鎖的衝突機率更大。
表鎖的衝突機率更大,因此併發性能更低,這裏併發性能就是小於。bash

InnoDB 裏面咱們知道它既支持表鎖又支持行鎖,另外一個經常使用的存儲引擎 MyISAM 支持什麼粒度的鎖?這是第一個問題。第二個就是 InnoDB 已經支持行鎖了,那麼它也能夠經過把表裏面的每一行都鎖住來實現表鎖,爲何還要提供表鎖呢?

要搞清楚這個問題,咱們就要來了解一下 InnoDB 裏面的基本的鎖的模式(lock mode),這裏面有兩個行鎖和兩個表鎖。

共享鎖

第一個行級別的鎖就是咱們在官網看到的 Shared Locks (共享鎖),咱們獲取了一行數據的讀鎖之後,能夠用來讀取數據,因此它也叫作讀鎖,注意不要在加上了讀鎖之後去寫數據,否則的話可能會出現死鎖的狀況。並且多個事務能夠共享一把讀鎖。那怎麼給一行數據加上讀鎖呢?

咱們能夠用 select …… lock in share mode; 的方式手工加上一把讀鎖。

釋放鎖有兩種方式,只要事務結束,鎖就會自動事務,包括提交事務和結束事務。

咱們也來驗證一下,看看共享鎖是否是能夠重複獲取。

Transaction 1 Transaction 2
begin;
SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE;
- begin;
- SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE;// OK

排它鎖

第二個行級別的鎖叫作 Exclusive Locks(排它鎖),它是用來操做數據的,因此又叫作寫鎖。只要一個事務獲取了一行數據的排它鎖,其餘的事務就不能再獲取這一行數據的共享鎖和排它鎖。

排它鎖的加鎖方式有兩種,第一種是自動加排他鎖。咱們在操做數據的時候,包括增刪改,都會默認加上一個排它鎖。

還有一種是手工加鎖,咱們用一個 FOR UPDATE 給一行數據加上一個排它鎖,這個不管是在咱們的代碼裏面仍是操做數據的工具裏面,都比較經常使用。

釋放鎖的方式跟前面是同樣的。

排他鎖的驗證:

Transaction 1 Transaction 2
begin;
UPDATE student SET sname = '貓老公 555' WHERE id=1;
- begin;
- SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE; // BLOCKED
- SELECT * FROM student where id=1 FOR UPDATE; // BLOCKED
- DELETE FROM student where id=1 ; // BLOCKED

這個是兩個行鎖,接下來就是兩個表鎖。

意向鎖

意向鎖是什麼呢?咱們彷佛曆來沒有聽過,也歷來沒有使用過,其實他們是由數據庫本身維護的。

也就是說,當咱們給一行數據加上共享鎖以前,數據庫會自動在這張表上面加一個意向共享鎖。

當咱們給一行數據加上排他鎖以前,數據庫會自動在這張表上面加一個意向排他鎖。

反過來講:

若是一張表上面至少有一個意向共享鎖,說明有其餘的事務給其中的某些數據行加上了共享鎖。

若是一張表上面至少有一個意向排他鎖,說明有其餘的事務給其中的某些數據行加上了排他鎖。

select * from t2 where id =4 for update;
複製代碼

TABLE LOCK table example.t2 trx id 24467 lock mode IX RECORD LOCKS space id 64 page no 3 n bits 72 index PRIMARY of table example.t2 trx id 24467 lock_mode X locks rec but not gap

那麼這兩個表級別的鎖存在的意義是什麼呢?第一個,咱們有了表級別的鎖,在InnoDB 裏面就能夠支持更多粒度的鎖。它的第二個做用,咱們想一下,若是說沒有意向鎖的話,當咱們準備給一張表加上表鎖的時候,咱們首先要作什麼?是否是必須先要去判斷有沒其餘的事務鎖定了其中了某些行?若是有的話,確定不能加上表鎖。那麼這個時候咱們就要去掃描整張表才能肯定能不能成功加上一個表鎖,若是數據量特別大,好比有上千萬的數據的時候,加表鎖的效率是否是很低?

可是咱們引入了意向鎖以後就不同了。我只要判斷這張表上面有沒有意向鎖,若是有,就直接返回失敗。若是沒有,就能夠加鎖成功。因此 InnoDB 裏面的表鎖,咱們能夠把它理解成一個標誌。就像火車上廁全部沒有人使用的燈,是用來提升加鎖的效率的。

Transaction 1 Transaction 2
begin;
SELECT * FROM student where id=1 FOR UPDATE;
- BEGIN;
- LOCK TABLES student WRITE; // BLOCKED
UNLOCK TABLES; // 釋放表鎖的方式

以上就是 MySQL 裏面的 4 種基本的鎖的模式,或者叫作鎖的類型。

By the way

有問題?能夠給我留言或私聊 有收穫?那就順手點個讚唄~

固然,也能夠到個人公衆號下「6曦軒」,

回覆「學習」,便可領取一份 【Java工程師進階架構師的視頻教程】~

回覆「面試」,能夠得到: 【本人嘔心瀝血整理的 Java 面試題】

回覆「MySQL腦圖」,能夠得到 【MySQL 知識點梳理高清腦圖】

因爲我咧,科班出身的程序員,php,Android以及硬件方面都作過,不過最後仍是選擇專一於作 Java,因此有啥問題能夠到公衆號提問討論(技術情感傾訴均可以哈哈哈),看到的話會盡快回復,但願能夠跟你們共同窗習進步,關於服務端架構,Java 核心知識解析,職業生涯,面試總結等文章會不按期堅持推送輸出,歡迎你們關注~~~

在這裏插入圖片描述
相關文章
相關標籤/搜索