MySQL數據庫鎖機制

鎖是計算機協調多個進程或純線程併發訪問某一資源的機制。在數據庫中,除傳統的計算資源(CPU、RAM、I/O)的爭用以外,數據也是一種供許多用戶共享的資源。如何保證數據併發訪問的一致性、有效性是所在有數據庫必須解決的一個問題,鎖衝突也是影響數據庫併發訪問性能的一個重要因素。在MySQL數據庫中支持多種不同粒度的鎖來兼顧數據庫併發與一致性問題。本文主要描述MySQL鎖工作機制及其鎖類型,粒度等。

一、MySQL數據庫鎖管理機制

SQL層實現的鎖機制
   Meta-data元數據鎖:在table cache緩存裏實現的,爲DDL(Data Definition Language)提供隔離操作。一種特別的meta-data元數據類型,叫Name Lock。
   表級table-level數據鎖
   全局讀鎖—FLUSH TABLES WITH READ LOCK

引擎層實現的鎖機制
   存儲引擎特有機制—row locks行鎖,page locks頁鎖,table locks表級,版本控制
在這裏插入圖片描述

二、鎖執行流程

計算語句使用到的所有表
在每個表:打開open表—從table cache緩存裏得到TABLE對象,並在此表加上meta-data元數據鎖
等待全局讀鎖後改變數據
在每個表:鎖lock表—在表加上table-level數據鎖
執行語句:調用:handler::write_row()/read_rnd()/read_index()等;隱式地調用引擎級engine-level鎖機制
在每個表:釋放表的數據鎖
在每個表:釋放表的DDL鎖並把表放回table?cache緩存裏
DDL語句也是一樣,沒有典型的執行計劃
在這裏插入圖片描述

三、鎖粒度

共享鎖(S):允許一個事務去讀一行
排他鎖(X):允許一個事務更新或刪除一行
事務A鎖住了表中的一行,讓這一行只能讀,不能寫。之後,事務B申請整個表的寫鎖。如果事務B申請成功,那麼理論上它就能修改表中的任意一行,這與A持有的行鎖是衝突的。數據庫需要避免這種衝突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。數據庫要怎麼判斷這個衝突呢?
普通認爲兩步:
   step1:判斷表是否已被其他事務用表鎖鎖表。
   step2:判斷表中的每一行是否已被行鎖鎖住。但是這樣的方法效率很低,因爲要遍歷整個表。
所以解決方案是:意向鎖。

InnoDB支持多粒度鎖定,這種鎖定允許在行級上的鎖和表級上的鎖同時存在。因此InnoDB還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表級鎖。用於解決表級鎖和行級鎖之間的衝突
   意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。
   意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。

間隙鎖
當我們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但不存在的記錄,叫做“間隙(GAP)”,InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(NEXT-KEY)鎖。

因爲Query執行過程中通過範圍查找的話,他會鎖定整個範圍內所有的索引鍵值,即使這個鍵值並不存在。
間隙鎖有一個比較致命的弱點,就是當鎖定一個範圍鍵值之後,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時候無法插入鎖定值範圍內的任何數據,在某些場景下這可能會針對性造成很大的危害。
在這裏插入圖片描述

四、InnoDB行級鎖

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章