MySQL高級知識(十四)——行鎖

前言:前面學習了表鎖的相關知識,本篇主要介紹行鎖的相關知識。行鎖偏向InnoDB存儲引擎,開銷大,加鎖慢,會出現死鎖,鎖定粒度小,發生鎖衝突的機率低,但併發度高。html


0.準備

#1.建立相關測試表tb_innodb_lock,注意數據庫引擎爲InnoDB數據庫

drop table if exists test_innodb_lock; CREATE TABLE test_innodb_lock ( a INT (11), b VARCHAR (20) ) ENGINE INNODB DEFAULT charset = utf8; insert into test_innodb_lock values (1,'a'); insert into test_innodb_lock values (2,'b'); insert into test_innodb_lock values (3,'c'); insert into test_innodb_lock values (4,'d'); insert into test_innodb_lock values (5,'e');

#2.建立索引。併發

create index idx_lock_a on test_innodb_lock(a); create index idx_lock_b on test_innodb_lock(b);

1.行鎖定基本演示

#1.打開A、B另個會話,並關閉數據庫的自動提交。高併發

set autocommit=0;

#2.在A會話中作更新操做。性能

從查詢結果可知:在A會話中更新數據成功。學習

#3.在B會話中作查詢操做。測試

分析:優化

B會話中並無讀取到A會話中更新後的值。(讀己知所寫:本身更改的數據本身知道,可是若是未提交,其餘人是不知道的。spa

#4.在A會話中執行commit命令,而後在B會話中再次查詢。設計

#5.在A會話中作更新操做,而後在B會話中也作更新操做。

這時在A會話中commit操做,可看到B會話中發生了更新操做。

分析:

由於咱們操做的同一行數據,而因爲InnoDB爲行鎖,在A會話未提交時,B會話只有阻塞等待。若是操做不一樣行,則不會出現阻塞狀況。

2.索引失效致使行鎖升級爲表鎖

#1.在A會話中執行以下更新語句。

#2.在B會話中執行以下更新語句。

分析:

首先將表中的數據更新爲b=1000,2000,3000,4000,5000。

在A會話中操做的第一行數據,可是where中使用了b=1000,發生了自動轉換致使索引失效,從而使鎖的級別從行鎖升級爲表鎖,所以B會話中操做第五行數據出現阻塞的狀況。

3.間隙鎖的危害

#1.間隙鎖定義:

當咱們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖,對於鍵值在條件範圍內但不存在的記錄,叫做「間隙(GAP)」。

InnoDB也會對這個「間隙」加鎖,這種鎖機制就是所謂的間隙鎖。(Next-Key鎖)

#2.間隙鎖危害:

由於在Query執行過程當中經過範圍查找的話,會鎖定整個範圍內的全部索引鍵值即便這個索引不存在。間隙鎖有一個比較致命的弱點,就是當鎖定一個範圍鍵值後,即便某些不存在的鍵值也會被無辜的鎖定,而形成在鎖定的時候沒法插入鎖定值範圍內的任何數據。在某些場景下這個可能會對性能形成很大的危害。

#3.間隙鎖演示。

要演示間隙鎖,咱們須要對test_innodb_lock中的數據進行修改,修改後的數據以下:

注:a列的值並不連續。

①在A會話中執行以下語句。

②在B會話中執行以下語句。

只有在A會話commit後,B會話才能進行插入操做。

4.如何鎖定某一行

利用for update

①在A會話中執行以下語句。

此時就鎖定了a=7這一行。

②在B會話中對該行進行更新操做。

只有在A會話中進行了commit後,B會話的更新操做才能執行。

5.行鎖分析

#1.使用以下命令。

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:從系統啓動到如今鎖等待最長的一次所花的時間。

Innodb_row_lock_waits:系統啓動後到如今總共等待鎖的次數。

這個五個狀態量中,比較重要的是:

Innodb_row_lock_time、Innodb_row_lock_time_avgInnodb_row_lock_waits。尤爲是等待次數很高,並且每次等待時長不小時,就須要分析優化了。

6.優化建議

①儘量讓全部數據都經過索引來完成,避免無索引行升級爲表鎖

②合理設計索引,儘可能縮小鎖的範圍。

③儘量使用較少的檢索條件,避免間隙鎖。

④儘可能控制事務大小,減小鎖定資源量和時間長度。

⑤儘量下降事務隔離級別。

7.頁鎖

開銷和加鎖時間介於表鎖和行鎖之間,會出現死鎖,鎖定粒度介於表鎖和行鎖之間,併發度通常(瞭解便可)。

總結

①InnoDB存儲引擎因爲實現了行級鎖定,雖然在鎖定機制的實現方面所帶來的性能損耗可能比表級鎖定會更高一些(多個鎖,一個鎖),可是在總體併發處理能力方面要遠遠優於MyISAM的表級鎖定。當系統處於高併發量的時候,InnoDB的總體性能和MyISAM相比就會有比較明顯的優點了。

②InnoDB的行鎖定一樣尤爲脆弱的一面(間隙鎖危害),當使用不當時可能會讓InnoDB的總體性能表現不只不能比MyISAM高,甚至可能更差。


by Shawn Chen,2018.6.28日,下午。


相關內容 

MySQL高級知識系列目錄

相關文章
相關標籤/搜索