mysql 鎖機制

来源:https://www.cnblogs.com/gaogch/archive/2019/08/05/11306436.html
-Advertisement-
Play Games

前言 大概幾個月之前項目中用到事務,需要保證數據的強一致性,期間也用到了mysql的鎖,但當時對mysql的鎖機制只是管中窺豹,所以本文打算總結一下mysql的鎖機制。 本文主要論述關於mysql鎖機制,mysql版本為5.7,引擎為innodb,由於實際中關於innodb鎖相關的知識及加鎖方式很多 ...


前言

  大概幾個月之前項目中用到事務,需要保證數據的強一致性,期間也用到了mysql的鎖,但當時對mysql的鎖機制只是管中窺豹,所以本文打算總結一下mysql的鎖機制。

  本文主要論述關於mysql鎖機制,mysql版本為5.7,引擎為innodb,由於實際中關於innodb鎖相關的知識及加鎖方式很多,所以沒有那麼多精力羅列所有場景下的加鎖過程並加以分析,僅根據現在瞭解的知識,結合官方文檔,說說自己的理解,如果發現有不對的地方,歡迎指正。

概述

  總的來說,InnoDB共有七種類型的鎖:

  • 共用/排它鎖(Shared and Exclusive Locks)
  • 意向鎖(Intention Locks)
  • 記錄鎖(Record Locks)
  • 間隙鎖(Gap Locks)
  • 臨鍵鎖(Next-key Locks)
  • 插入意向鎖(Insert Intention Locks)
  • 自增鎖(Auto-inc Locks)

mysql鎖詳解

1. 共用/排它鎖(Shared and Exclusive Locks)

  • 共用鎖(Share Locks,記為S鎖),讀取數據時加S鎖
  • 排他鎖(eXclusive Locks,記為X鎖),修改數據時加X鎖

  使用的語義為:

  • 共用鎖之間不互斥,簡記為:讀讀可以並行
  • 排他鎖與任何鎖互斥,簡記為:寫讀,寫寫不可以並行

  可以看到,一旦寫數據的任務沒有完成,數據是不能被其他任務讀取的,這對併發度有較大的影響。對應到資料庫,可以理解為,寫事務沒有提交,讀相關數據的select也會被阻塞,這裡的select是指加了鎖的,普通的select仍然可以讀到數據(快照讀)。

2. 意向鎖(Intention Locks)

  InnoDB為了支持多粒度鎖機制(multiple granularity locking),即允許行級鎖與表級鎖共存,而引入了意向鎖(intention locks)。意向鎖是指,未來的某個時刻,事務可能要加共用/排它鎖了,先提前聲明一個意向。

  1. 意向鎖是一個表級別的鎖(table-level locking);
  2. 意向鎖又分為:
    • 意向共用鎖(intention shared lock, IS),它預示著,事務有意向對錶中的某些行加共用S鎖;
    • 意向排它鎖(intention exclusive lock, IX),它預示著,事務有意向對錶中的某些行加排它X鎖;

  加鎖的語法為:

select ... lock in share mode;  要設置IS鎖;
select ... for update;       要設置IX鎖;

  事務要獲得某些行的S/X鎖,必須先獲得表對應的IS/IX鎖,意向鎖僅僅表明意向,意向鎖之間相互相容,相容互斥表如下:

  IS IX
IS 兼 容 兼 容
IX 兼 容 兼 容

 

 

 

 

  雖然意向鎖之間互相相容,但是它與共用鎖/排它鎖互斥,其相容互斥表如下:

  S X
IS 兼 容 互 斥
IX 互 斥 互 斥

 

 

 

 

  排它鎖是很強的鎖,不與其他類型的鎖相容。這其實很好理解,修改和刪除某一行的時候,必須獲得強鎖,禁止這一行上的其他併發,以保障數據的一致性。

3. 記錄鎖(Record Locks)

  記錄鎖,它封鎖索引記錄,例如(其中id為pk):

create table lock_example(id smallint(10),name varchar(20),primary key id)engine=innodb;

  資料庫隔離級別為RR,表中有如下數據:

10, zhangsan
20, lisi
30, wangwu
select * from t where id=1 for update;

  其實這裡是先獲取該表的意向排他鎖(IX),再獲取這行記錄的排他鎖(我的理解是因為這裡直接命中索引了),以阻止其他事務插入,更新,刪除id=1的這一行。

4. 間隙鎖(Gap Locks)

  間隙鎖,它封鎖索引記錄中的間隔,或者第一條索引記錄之前的範圍,又或者最後一條索引記錄之後的範圍。依然是上面的例子,InnoDB,RR:

select * from lock_example
    where id between 8 and 15 
    for update;

  這個SQL語句會封鎖區間(8,15),以阻止其他事務插入id位於該區間的記錄。

  間隙鎖的主要目的,就是為了防止其他事務在間隔中插入數據,以導致“不可重覆讀”。如果把事務的隔離級別降級為讀提交(Read Committed, RC),間隙鎖則會自動失效。

5. 臨鍵鎖(Next-key Locks)

  臨鍵鎖,是記錄鎖與間隙鎖的組合,它的封鎖範圍,既包含索引記錄,又包含索引區間。

  預設情況下,innodb使用next-key locks來鎖定記錄。但當查詢的索引含有唯一屬性的時候,Next-Key Lock 會進行優化,將其降級為Record Lock,即僅鎖住索引本身,不是範圍。

  舉個例子,依然是如上的表lock_example,但是id降級為普通索引(key),也就是說即使這裡聲明瞭要加鎖(for update),而且命中的是索引,但是因為索引在這裡沒有UK約束,所以innodb會使用next-key locks,資料庫隔離級別RR:

事務A執行如下語句,未提交:
select * from lock_example where id = 20 for update;

事務B開始,執行如下語句,會阻塞:
insert into lock_example values('zhang',15);

  如上的例子,事務A執行查詢語句之後,預設給id=20這條記錄加上了next-key lock,所以事務B插入10(包括)到30(不包括)之間的記錄都會阻塞。臨鍵鎖的主要目的,也是為了避免幻讀(Phantom Read)。如果把事務的隔離級別降級為RC,臨鍵鎖則也會失效

6. 插入意向鎖(Insert Intention Locks)

  對已有數據行的修改與刪除,必須加強互斥鎖(X鎖),那麼對於數據的插入,是否還需要加這麼強的鎖,來實施互斥呢?插入意向鎖,孕育而生。

  插入意向鎖,是間隙鎖(Gap Locks)的一種(所以,也是實施在索引上的),它是專門針對insert操作的。多個事務,在同一個索引,同一個範圍區間插入記錄時,如果插入的位置不衝突,不會阻塞彼此。

Insert Intention Lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

  舉個例子(表依然是如上的例子lock_example,數據依然是如上),事務A先執行,在10與20兩條記錄中插入了一行,還未提交:

insert into t values(11, xxx);

  事務B後執行,也在10與20兩條記錄中插入了一行:

insert into t values(12, ooo);

  因為是插入操作,雖然是插入同一個區間,但是插入的記錄並不衝突,所以使用的是插入意向鎖,此處A事務並不會阻塞B事務。

7. 自增鎖(Auto-inc Locks)

  自增鎖是一種特殊的表級別鎖(table-level lock),專門針對事務插入AUTO_INCREMENT類型的列。最簡單的情況,如果一個事務正在往表中插入記錄,所有其他事務的插入必須等待,以便第一個事務插入的行,是連續的主鍵值。

AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.

  舉個例子(表依然是如上的例子lock_example),但是id為AUTO_INCREMENT,資料庫表中數據為:

1, zhangsan
2, lisi
3, wangwu

  事務A先執行,還未提交: insert into t(name) values(xxx);

  事務B後執行: insert into t(name) values(ooo);

  此時事務B插入操作會阻塞,直到事務A提交。

總結

   以上總結的7種鎖,個人理解可以按兩種方式來區分:

  1. 按鎖的互斥程度來劃分,可以分為共用、排他鎖;

  • 共用鎖(S鎖、IS鎖),可以提高讀讀併發;
  • 為了保證數據強一致,InnoDB使用強互斥鎖(X鎖、IX鎖),保證同一行記錄修改與刪除的串列性;

  2. 按鎖的粒度來劃分,可以分為:

  • 表鎖:意向鎖(IS鎖、IX鎖)、自增鎖;
  • 行鎖:記錄鎖、間隙鎖、臨鍵鎖、插入意向鎖;

  其中

  1. InnoDB的細粒度鎖(即行鎖),是實現在索引記錄上的(我的理解是如果未命中索引則會失效);  
  2. 記錄鎖鎖定索引記錄;間隙鎖鎖定間隔,防止間隔中被其他事務插入;臨鍵鎖鎖定索引記錄+間隔,防止幻讀;
  3. InnoDB使用插入意向鎖,可以提高插入併發;
  4. 間隙鎖(gap lock)與臨鍵鎖(next-key lock)只在RR以上的級別生效,RC下會失效
===================================== 臨淵羡魚,不如退而結網 =====================================
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在沒有git add之前: #撤銷所有更改 git checkout . #撤銷指定文件的更改 git checkout -- myfile.txt ...
  • 1、Shell命令行解釋器 1.1 Shell命令解釋器 Shell是一個特殊的應用程式,介於操作系統內核和用戶之間,負責接收用戶輸入的操作指令(命令)併進行解釋,將需要執行的操作傳遞給內核執行。 因此Shell程式在系統中充當了一個“命令解釋器”的角色。類似於windows系統的cmd.exe命令 ...
  • NETCAT netcat是Linux常用的網路工具之一,它能通過TCP和UDP在網路中讀寫數據,通過與其他工具結合和重定向,可以在腳本中以多種方式使用它。 netcat所做的就是在兩臺電腦之間建立鏈接並返回兩個數據流,我們可以建立一個伺服器,傳輸文件,與朋友聊天,傳輸流媒體或者用它作為其它協議的獨 ...
  • step1: 安裝虛擬環境: export WORKON_HOME=$HOME/.virtualenvs #指定virtualenvwrapper環境的目錄 export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3.6 #指定virtualenvwrapper ...
  • postfix 虛擬用戶 postfix + dovecot + openldap 製作虛擬郵件用戶 這裡使用的虛擬郵件用戶的方法是我自己研究的,可能會有不對或則不好的地方,望指出。由於之前已經寫過MariaDB作為資料庫的虛擬用戶,所以這裡會有很多地方會簡化配置和講解,如果沒有看懂可以看看這篇文章 ...
  • 一、查看登錄用戶信息 w [用戶名] 二、Who who 三、查詢當前登錄和過去登陸的用戶信息 last 四、查看所有用戶最後一次登錄時間 lastlog ...
  • Linux強制關掉其他ssh登錄的用戶 首先 用who命令查看登錄的iproot pts/0 162.16.16.155 14:30 0.00s 0.07s 0.05s wroot pts/1 162.16.16.155 14:30 12.00s 0.01s 0.01s -bash 然後who am ...
  • Ctrl+N 當前位置新視窗打開Ctrl+Enter 點擊的文件夾新視窗打開 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...