MySQL鎖機制

MySQL鎖機制

MySQL鎖概述

鎖是數據庫系統區分與文件系統的一個關鍵特性。鎖機制用於管理對共享資源的併發訪問。

MySQL鎖級別

鎖級別 性能分析
表級別 開銷小,加鎖快;不會出現死鎖;鎖定力度大,發生鎖衝突概率高,併發度最低
行級鎖 開銷大,加鎖慢;會出現死鎖;鎖定粒度小,發生鎖衝突的概率低,併發度高
頁級鎖 開銷和加鎖速度介於表鎖和行鎖之間;會出現死鎖;鎖定粒度介於表鎖和行鎖之間,併發度一般

MyISAM 表鎖

 表鎖介紹

表鎖是MySql中最基本的鎖策略,並且是開銷最小的策略,表鎖將整張表加鎖。

表鎖模式:表共享讀鎖表獨佔寫鎖

表鎖兼容性
當前鎖模式/請求鎖模式 讀鎖 寫鎖
讀鎖 兼容 不兼容
寫鎖 不兼容 不兼容

1. 當一個進程獲得了表的讀鎖,不會阻塞其他進程對同一表的讀請求,但會阻塞其他進程對錶的寫請求。
這裏寫圖片描述
2. 當一個進程獲取表的寫鎖,會阻塞其他進程獲得表的讀請求和寫請求。
這裏寫圖片描述

MyISAM併發插入

在一定條件下,MyISAM表頁支持查詢和插入的併發操作。MyISAM存儲引擎有一個系統變量concurrent_insert,用以控制其併發插入的行爲,取值0、1或2。

  • 當concurrent_insert = 0時,不允許併發插入;
  • 當concurrent_insert = 1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄。這也是MySQL的默認設置。
  • 當concurrent_insert = 2時,無論MyISAM表中有沒有空洞,都允許在表尾併發插入記錄。

MyISAM鎖調度

mysql認爲寫請求一般比讀請求重要。當一個進程請求表的讀鎖,同時另一個進程請求同一個表的寫鎖,寫進程將優先獲得鎖。即使是讀請求先到鎖等待隊列,寫請求後到,寫鎖也會優先獲取鎖。這也正是MyISAM表不太適合有大量更新操作和查詢操作的應用的原因,大量的更新操作會造成查詢操作很難獲得鎖。

可以通過以下方式調節MyISAM鎖調度行爲

  • 通過指定啓動參數low-priority-updates,使MyISAM引擎默認給予讀請求以優先的權利。
  • 通過執行命令SET LOW_PRIORITY_UPDATES=1,使該連接發出的更新請求優先級降低。
  • 通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優先級。
  • MySQL也提供了一種折中的辦法來調節讀寫衝突,即給系統參數max_write_lock_count設置一個合適的值,當一個表的讀鎖達到這個值後,MySQL就暫時將寫請求的優先級降低,給讀進程一定獲得鎖的機會。

 MyISAM優化建議

縮短鎖定時間、分離並行的操作、合理利用讀寫優先級、讀寫分離

InnoDB 行鎖

鎖的類型

InnoDB實現了一下兩種標準的行級鎖:

  • 共享鎖(S):鎖粒度是行或者元組(多行)。一個事務獲得了共享鎖之後,就可以對鎖定範圍內的數據進行讀操作。
  • 排他鎖(X):鎖粒度是行或者元組(多行)。一個事務獲得排他鎖之後,就可以對鎖定範圍內的數據執行insert/delete/update操作。

另外,爲了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖(Intention Locks),
這兩種意向鎖都是表鎖。

  • 意向共享鎖(IS):事務在給一個數據行加S鎖前必須先取得該表的IS鎖。
  • 意向排他鎖(IX):事務在給一個數據行加X鎖前必須先取得該表的IX鎖。

InnoDB鎖的兼容性

當前鎖模式/請求鎖模式 IS IX S X
IS 兼容 兼容 兼容 不兼容
IX 兼容 兼容 不兼容 不兼容
S 兼容 不兼容 兼容 不兼容
X 不兼容 不兼容 不兼容 不兼容

行鎖的算法

  1. 單個行記錄上的鎖(Record Lock):單個單索引記錄上的鎖。
  2. 間隙鎖(Gap Lock):鎖定一個範圍,但不包括記錄本身。GAP鎖的目的,是爲了防止同一事務的兩次當前讀,出現幻讀的情況。
  3. 鎖定一個範圍,並且鎖定記錄本身 (Next-Key Lock = Gap Lock + Record Lock):
    Next-Key Lock結合了Gap Lock + Record Lock的一種鎖定算法。鎖定一個範圍,並且鎖定記錄本身。在MySQL默認的事務隔離級別(REPEATABLE READ)下,InnoDB通過這種機制來防止出現幻讀的情況。

死鎖

死鎖是指兩個或兩個以上的事務在執行的過程中,因爭奪鎖資源而造成相互等待的現象。若無外力的作用,事務將無法推進下去。死鎖出現的概率是非常低的。

解決死鎖問題最簡單的一種方式是超時,即當兩個事務相互等待時,當一個等待時間超過某個值時,其中一個事務進行回滾,另一個等待事務就能繼續進行。InnoDB可通過參數innodb_lock_wait_timeout來設置超時的時間。

除了超時機制,當前數據庫較多采用wait-for graph(等待圖)方式來進行死鎖檢測,這是一種更爲主動的檢測方式。
innodb內置有死鎖檢查機制。當出現死鎖時會自動回滾佔用undo資源少的事務。死鎖的檢測除了超時還有wait-for graph,如果圖中出現環形迴路則表明存在死鎖。wait-for graph要求數據庫保存鎖的信息鏈表事務等待鏈表表兩種信息,通過鏈表可以構造一張圖,而在這個圖中若存在迴路就代表存在死鎖,因此資源間相互發生等待。每個事務在請求鎖併發生等待是都會判斷是否存在迴路,若存在則有死鎖,通常InnoDB會選擇回滾undo量最小的事務。

—————END—————

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