Mysql Innodb 鎖機制

来源:https://www.cnblogs.com/magicsoar/archive/2018/02/04/8414638.html
-Advertisement-
Play Games

Innodb中的鎖類型,常見的insert,delete,update如何加鎖,update會死鎖,3個insert可以死鎖?3個delete也會死鎖? ...


latch與lock

latch 可以認為是應用程式中的鎖,可以稱為閂鎖(輕量級的鎖) 因為其要求鎖定的時間必須要非常短,若持續時間長,則會導致應用性能非常差,在InnoDB存儲引擎中,latch又可以分為mutex(互斥鎖)和rwlock(讀寫鎖),其目的用來保證併發線程操作臨界資源的正確性,並且沒有死鎖檢測的機制

 

在InnoDB存儲引擎中的latch,可以通過命令SHOW ENGINE INNODB MUTEX 來進行查看

mysql > SHOW ENGINE INNODB MUTEX;

 

NewImage 

 

lock可以認為是資料庫提供的鎖,用來鎖定的是資料庫中的數據。並且一般lock對象僅在事務commit或rollback後進行釋放(不同事務隔離級別釋放的時間可能不同),lock是有死鎖機制的。

在InnoDB存儲引擎中的lock 可以通過show engine innodb status,information_schema.INNODB_LOCKS,INNODB_TRX,INNODB_LOCK_WATIS信息來查看

NewImage 

線程獲取lock的流程:

在對數據加lock的時候會先對數據所在的頁面添加latch,然後再對數據添加lock,添加完lock後再釋放頁面的Latch。

這種機制主要是為了保證線程獲取的行數據的一致性和完整性.

如果lock被其他的線程占有,線程先釋放頁面latch,等待lock,待獲取lock後會再次對頁面添加latch,查看頁面數據是否有改動,然後嘗試再次獲取對應的lock

 

 

共用鎖與排他鎖

innodb儲存引擎提供瞭如下兩種標準的行級鎖

共用鎖(S) 允許一個事務去讀一行

排他鎖(X) 允許獲得排他鎖的事務更新或刪除數據

 

同時innodb儲存引擎支持多粒度鎖定,為了支持在不同的粒度上進行加鎖操作,innodb支持另一種額外的鎖方式,稱之為意向鎖

 

意向共用鎖(IS)  事務想要獲得一張表中某幾行的共用鎖

意向排他鎖(IX)事務想要獲得一張表中某幾行的排他鎖

 

在行鎖的實現上

mysql提供了三種的行鎖的演算法

分別是

Record Lock 記錄鎖,單個記錄上的鎖

Gap Lock 間隙鎖,鎖定一個範圍,但不包含記錄本身

Next-key Lock Gap Lock + Record Lock 鎖定一個範圍,並且鎖定記錄本身

 

 

Mysql是如何加鎖的

非特殊註明 預設在RR隔離級別下進行討論

InnoDb的行鎖是對索引加鎖的,對掃描的行邊掃描邊加鎖,如果走的是二級索引(非聚簇索引)除了需要對二級索引加鎖外,還需要根據二級索引裡面的主鍵信息掃描主鍵的聚簇索引,對主鍵加鎖,

 加鎖的數據行數會受到Mysql是否支持Index Condition PushDown而影響(Mysql 5.6支持ICP),加鎖的數量可能遠遠大於滿足條件的記錄數量

這裡需要加兩次鎖的原因是

如果

語句A 使用二級索引對記錄X進行更新操作,

語句B使用聚簇索引對記錄X進行更新操作,

如果A僅對二級索引進行加鎖,那麼併發的語句B將感受不到語句A的存在,違背了同一條記錄上的更新/刪除必須串列執行的約束

select * from table where?

RC級別下 : 無需加鎖,一致性非鎖定讀,使用快照讀,讀取被鎖定行的最新一份數據,因此會出現前後讀取數據不一致的情況

RR級別下:無需加鎖,一致性非鎖定讀,使用快照讀,讀取事務開始時的行數據版本,因此前後讀到的數據是一樣的

Serializable級別下:使用當前讀,需要加鎖,innodb內部將select語句轉換為了select … lock in share mode

 

insert?

insert會對插入成功的行加上記錄鎖,不會阻止其他併發的事務往這條記錄之前插入記錄。在插入之前,會先在插入記錄所在的間隙加上一個插入意向意向鎖(併發的事務可以對同一個間隙加插入意向鎖鎖)。如果insert 的事務出現了duplicate-key error ,事務會對duplicate index record的記錄加共用鎖。這個共用鎖在併發的情況下是會產生死鎖的,比如有兩個併發的insert都對要對同一條記錄加共用鎖,而此時這條記錄又被其他事務加上了排它鎖,排它鎖的事務將這條記錄刪除後,兩個併發的insert操作會發生死鎖。

 

delete?

delete操作僅是將主鍵列中對對應的記錄delete flag設置為1,記錄並沒有被刪除,還是存在於B+樹中

真正的刪除操作被延遲了,最終在purge操作中完成

延遲到purge操作的原因是的innodb支持mvcc多版本控制,所以記錄不能在事務提交時立即進行刪除,只有當對應的行記錄不被任何其他事務引用的時候,才可以由purge進行真正的刪除

delete操作過程中:

找到滿足條件的記錄,並且記錄有效,則對記錄加X鎖

找到滿足條件的記錄,但是記錄無效(標識為刪除),則對記錄加next key鎖、;

未找到滿足條件的記錄,則對第一個不滿足條件的記錄加Gap鎖,保證沒有滿足條件的記錄插入;

 

update?

對滿足條件的記錄next-key鎖,如果是等值匹配並且使用唯一索引或是聚簇索引,那麼可以只添加記錄鎖

 

 

唯一索引中含NULL值的記錄,將不會添加記錄鎖,轉而為next-key鎖 因為NULL不等於NULL,NULL和任何值比較均返回NULL,包括NULL本身,但是 NULL is NULL

 

死鎖案例分析

create table `deadlocktest`

(

`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,

`a` bigint(20) unsigned NOT NULL,

`b` bigint(20) unsigned NOT NULL,

`c` bigint(20) unsigned NOT NULL,

`d` bigint(20) unsigned NOT NULL,

`e` bigint(20) unsigned NOT NULL,

PRIMARY KEY(`id`),

UNIQUE KEY `I_a`(`a`),

KEY `I_b` (`b`),

KEY `I_c` (`c`)

)ENGINE=InnoDb ;

 

insert into deadlocktest (a,b,c,d,e)values(1,999,3,4,5);

insert into deadlocktest (a,b,c,d,e)values(2,998,4,5,6);

insert into deadlocktest (a,b,c,d,e)values(3,997,4,5,6);

insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5);

...

insert into deadlocktest (a,b,c,d,e)values(1000,1,3,4,5);

 

3個insert的死鎖

事務A

事務B

事務C

begin;

begin;

begin;

insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5);

 

 

 

insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5);

 

 

 

insert into deadlocktest (a,b,c,d,e)values(4,996,3,4,5);

rollback;

 

 

 

1 row affected

Deadlock found when trying to get lock; try restarting transaction

 

事務A 獲得排他鎖,插入數據成功

事務B 事務C,因為記錄duplicate-key error轉而持有行的共用鎖

事務A回滾,釋放了持有的排他鎖,事務B和事務C需要獲得該行的排他鎖,但是由於互相都持有對應行的共用鎖,互相等待,造成死鎖

 

2個update的死鎖

事務A

事務B

begin;

begin;

update deadlocktest force index(I_b) set e = sleep(5) where b>0;

 

 

update deadlocktest force index(I_c) set e = sleep(5) where c>2;

Deadlock found when trying to get lock; try restarting transaction

Rows matched: 4  Changed: 4  Warnings: 0

兩個update事務,加鎖順序不一樣導致的死鎖

InnoDb的行鎖是對索引加鎖的,對掃描的行邊掃描邊加鎖,如果走的是二級索引(非聚簇索引)除了需要對二級索引加鎖外,還需要根據二級索引裡面的主鍵信息掃描主鍵的聚簇索引,對主鍵加鎖

3個以上delete的死鎖

事務A

事務B

事務B

begin;

begin;

 begin

delete from deadlocktest where a=550

 

 

 

delete from deadlocktest where a=550

 
 

 

 

delete from deadlocktest where a=550

commit; 0 rows affected  Deadlock found when trying to get lock; try restarting transaction

delete操作僅是將主鍵列中對對應的記錄delete flag設置為1,實際的刪除延遲到purge中

delete刪除時如果找到滿足條件的記錄,但是記錄無效(標識為刪除),則對記錄加next key鎖、;

死鎖日誌

NewImage

3個delete的死鎖比較難以復現,我是利用如下腳本完成的

MY_DB="mysql -hxxx -Pxxx -uxxx -pxxx"

while :
do
echo "use test;begin; delete from deadlocktest where a=499;rollback;" | $MY_DB
done

該類delete死鎖的出現條件

1、針對唯一索引上等值查詢的刪除

2、有3個以上併發刪除操作

3、事務的隔離級別是RR

4、INNODB儲存引擎

 

參考文獻

https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

http://hedengcheng.com/?p=771#_Toc374698320

http://hedengcheng.com/?p=844

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Entity Framework Codefirst的配置步驟: (1) 安裝命令: install-package entityframework (2) 創建實體類,註意virtual關鍵字在導航屬性中的用法 (3) 創建DbContext類,為每個entity set創建一個DbSet; 指定 ...
  • 1. 實現DataGrid column的顯示和隱藏功能; (1). 定義ContextMenu ,該ContextMenu僅可使用於DataGrid的DataGridColumnHeader; (2). 自定義顯示隱藏的制轉換器; 2. 在實現DataGridColumn Filter 功能時,可 ...
  • 本文目錄:1. Tomcat連接器協議類型2. Tomcat與httpd/nginx結合的方式3. Tomcat + nginx4. Tomcat + httpd(mod_jk) 4.1 編譯mod_jk模塊 4.2 配置httpd與tomcat的ajp連接 4.3 通過mod_jk負載均衡tomc ...
  • 簡介 IPC 主要有消息隊列、信號量和共用記憶體3種機制。和文件一樣,IPC 在使用前必須先創建,使用 ipcs 命令可以查看當前系統正在使用的 IPC 工具: 由以上可以看出,一個 IPC 至少包含 key值、ID值、擁有者、許可權和使用的大小等關鍵信息。如果需要手工刪除某個 IPC 機制,可以使用 ...
  • htpasswd用於為指定用戶生成基於網頁用戶身份認證的密碼,由httpd-tools軟體包提供。支持3種加密演算法:MD5、SHA和系統上的crypt()函數,不指定演算法時,預設為md5。 例如: (1).使用"-n"選項直接將結果輸出到標準輸出而不創建passwdfile。 (2).使用批處理模式 ...
  • 有些時候因為特殊需求,需要在已安裝的httpd上添加一些額外的模塊,這時候要使用httpd-devel中的apxs工具。要使用這個擴展機制,你的平臺必須支持DSO特性,即要求Apache httpd必須內建了mod_so模塊。 apxs添加模塊的方法很簡單,以下是幾個可能用上的選項。 -c mod_ ...
  • sed 是一種流編輯器,一次處理一行內容,處理時,把當前處理的行存儲在臨時緩衝區,稱為模式空間,接著用sed命令處理模式空間中的內容,處理完成後,把緩衝區的內容送往屏幕。然後讀入下行,執行下一個迴圈。 用法:sed [option]... 'script' inputfile... # :指定某行, ...
  • 在MySQL運維中,研發同事想對比下兩個不同實例上的數據並找出差異,除主鍵外還需要對比每一個欄位,如何做呢? 第一種方案,寫程式將兩個實例上的每一行數據取出來進行對比,理論可行,但是對比時間較長。 第二種方案,對每一行數據所有欄位合併起來,取checksum值,再按照checksum值對比,看著可行 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...