MySQL的鎖

MySql鎖

簡單介紹

  • 數據庫鎖機制簡單來講就是數據庫爲了保證數據的一致性而使各類共享資源在被併發訪問時,使得訪問有序所設計的一種規則數據庫

  • 鎖機制是針對存儲引擎的,不一樣的引擎有不一樣的優化設計併發

  • MySQL有三種類型的鎖定機制:行級鎖定、頁級鎖定、表級鎖定高併發

  • MySQL的InnoDB和MyISAM儲存引擎最大的區別就是:事務的支持、行級鎖的支持性能

三種鎖機制的理解

在上面咱們有講到MySQL有三種鎖機制,下面對其進行詳細的說明:學習

行級鎖定優化

  • 對一條數據進行鎖定,鎖定粒度最小,正是由於如此可以使得程序能夠儘量大的併發訪問數據庫,提高高併發系統的總體性能有優勢就有缺點,雖然在併發處理能力上有較大的優點,可是行級鎖的粒度最小,每次獲取鎖和釋放鎖都須要額外的消耗,此外行級鎖有死鎖隱患spa

頁級鎖定設計

  • 頁級鎖定是MySQL中比較特殊的一種鎖定機制,鎖定粒度介於行級鎖定和表級鎖定,也有死鎖隱患blog

表級鎖定索引

  • 直接將整個表鎖定,是MySQL中最大粒度的鎖定機制,最大的特色是實現邏輯很是簡單,帶來的系統負面影響最小,獲取與釋放鎖速度都很快,但因爲鎖定的粒度最大,處理併發需求很弱,但能夠消除死鎖隱患

可概括爲:

  • 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低;

  • 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高;

  • 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常。

對於表級鎖,還有點東西能夠叨嘮叨嘮

MySQL的表級鎖有兩種模式:表共享讀鎖、表獨佔寫鎖

查看錶級鎖定爭用狀態變量: show status like 'table%';

  • table_locks_immediate:產生表級鎖定的次數;

  • table_locks_waited:出現表級鎖定爭用而發生等待的次數;

  

  • 手動增長表鎖 : lock table 表名稱 read(write),表名稱2 read(write),其餘;

  • 查詢表鎖狀況:show open tables;

  • 刪除表鎖:unlock tables;

讀鎖

仍是講解一下:

  1. 首先咱們在第一個鏈接裏面 使用 lock table oyherTest read; 給otherTest表上了一個讀鎖

  2. 而後咱們再當前會話進行查詢,能夠發現咱們能夠查詢到數據

  3. 在當前鏈接,當咱們想往表中更改數據的時候,發現報錯了,若是其餘鏈接想更改數據,會處於等待狀態

  4. 當咱們使用 unlock tables; 釋放全部鎖的時候,其餘的鏈接對該表的更改會生效

寫鎖

InnoDB引擎的鎖機制

  1. 你們都知道,咱們當前使用的MySQL的默認儲存引擎就是InnoDB,下面對其的鎖機制進行學習

  2. 共享鎖:容許一個事務去讀一行,阻止其餘事務來獲取相同數據集的,是一個排它鎖

  3. 排它鎖:容許得到該鎖的事務更新數據,阻止其餘事務獲取相同數據集的共享讀鎖和排他寫鎖

  4. 對於update、delete、insert語句,InnoDB會自動給涉及數據集加排它鎖

  5. 對於普通select語句,InnoDB不會加任何鎖,事務能夠經過如下語句顯示給記錄集加共享鎖或排它鎖

    • 共享鎖:select * from table_name where ... lock in share mode;

    • 排它鎖:select * from table_name where ... for update;

  6. InnoDB行鎖是用過給索引項加鎖來實現的,所以InoDB這種行鎖實現的特色就意味着,只有經過索引條件檢索數據,InnoDB纔會使用行級鎖,不然,InnoDB將會使用表鎖;

InnoDb的行級鎖一樣分爲兩種類型:共享鎖、排它鎖

而在鎖定機制的實現過程當中爲了讓行級鎖和表級鎖共存,InnoDB使用了意向鎖,也就有了意向共享/排他鎖

  

InnoDb的鎖定是經過在指向數據記錄的第一個索引鍵以前和最後一個索引鍵以後的區間上標記鎖定信息,因此select 查詢過程當中經過範圍查詢的話,就會鎖定整個範圍內全部的索引鍵值,即便這個鍵值並不存在

演示區域

Innodb所使用的行級鎖定爭用狀態查看:show status like 'innodb_row_lock%';

  

  • Innodb_row_lock_current_waits:當前正在等待鎖定的數量;

  • Innodb_row_lock_time:從系統啓動到如今鎖定總時間長度;

  • Innodb_row_lock_time_avg:每次等待所花平均時間;

  • Innodb_row_lock_time_max:從系統啓動到如今等待最常的一次所花的時間;

  • lnnodb_row_lock_waits:系統啓動後到如今總共等待的次數;

行鎖的基本演示:

在有索引的狀況下,是行級鎖定  

  

  • 咱們依次設置關閉自動提交,這時會話一的鏈接會得到鎖

  • 而後咱們在更改表中的數據,在未commit以前,咱們在會話二中也對同一行數據進行更改,會處於阻塞狀態

  • 會話一commit提交後釋放鎖,此時處於阻塞狀態的會話二也相繼完成更改,最後提交

在無索引的狀況下升級爲表鎖

  

  • 在自動提交關閉的狀況下繼續演示,咱們不是用索引更改一條數據

  • 在還沒有提交的狀況下,咱們經過會話二,對錶中的其餘行數據進行更改,會處於阻塞狀態

  • 當會話一提交完成後,會話二相繼完成更改操做

至於死鎖的話,我就口頭表述一下:

  • 在自動提交關閉的狀況下,會話一使用索引對錶中的一行數據進行了更改,此時爲行級鎖定,

  • 會話二此時也經過索引對另外一條數據發生了更改操做,也是行級鎖定

  • 在上面的環境下,會話一相對會話二所操做的數據進行更改,會話二也想對會話一所操做的數據進行更改

  • 在他們雙方都沒有提交釋放鎖的前提下,雙雙等待對方釋放鎖,至死不休;

相關文章
相關標籤/搜索