1. 程式人生 > >MySQL高階-鎖機制詳解.md

MySQL高階-鎖機制詳解.md

概述

鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。

在資料庫中, 出傳統的計算資源(如CPU, RAM, IO等)的爭用以外, 資料也是一種供許多使用者共享的資源。如何保證資料併發訪問的一致性, 有效性是所有資料庫必須解決的一個問題, 鎖衝突也是影響資料庫併發訪問效能的一個重要因素。從這個角度來說, 鎖對資料庫而言顯得尤其重要, 也更加複雜。

鎖的分類

按照資料操作型別分類

讀鎖(共享鎖) : 針對同一份資料, 多個讀操作可以同時進行而不會互相影響。

寫鎖(排他鎖) : 當前寫操作沒有完成前, 會阻斷其他寫鎖和讀鎖

按照資料操作粒度來分

表鎖(偏讀)

MyISAM儲存引擎, 開銷小, 加鎖快, 無死鎖; 鎖定粒度大, 發生鎖衝突概率最高, 併發度最低。

  • MyISAM在執行查詢語句前, 會自動給涉及的所有表加讀鎖, 在執行增刪改操作前, 會自動給涉及的表加寫鎖。

  • MySQL的表級鎖有兩種模式:

    • 表共享讀鎖(Table Read Lock)

    • 表獨佔寫鎖(Table Write Lock)

      鎖型別 是否相容 讀鎖 寫鎖
      讀鎖
      寫鎖

總結:

結合上表, 所以對MyISAM表進行操作, 會有以下情況 :

  • 對MyISAM表的讀操作(加讀鎖), 不會阻塞其他程序對同一表的讀請求, 但會阻塞對同一表的寫請求。只有當讀鎖釋放後, 才會執行其它程序的寫操作

  • 對MyISAM表的寫操作(加寫鎖), 會阻塞其他程序對同一表的讀和寫操作, 只有當寫鎖釋放後, 才會執行其它程序的讀寫操作

    簡而言之, 就是讀鎖會阻塞寫, 但是不會阻塞讀。而寫鎖則會把讀和寫都阻塞。

表鎖分析

  • 檢視哪些表被加鎖了 : show open tables

  • 如何分析表鎖定 : 可以通過檢查table_locks_waited和table_locks_immediate狀態變數來分析系統上的表鎖定, 使用命令 : show status like ‘table%’;

    table_locks_immediate : 產生表級鎖定的次數, 表示可以立即獲取鎖的查詢次數, 每立即獲取鎖值加1

    table_locks_waited : 出現表級鎖定爭用而發生等待多的次數(不能立即獲取鎖的次數, 每等待一次鎖值加1), 此值高則說明存在著較嚴重的表級鎖爭用情況。

    1538452667749

  • 此外, MyISAM的讀寫鎖排程室寫優先, 這也是MyISAM不適合作為偏寫的引擎。因為寫鎖後, 其他執行緒不能做任何操作, 大量更新會使查詢很難得到鎖, 從而造成永久阻塞

行鎖

  • 偏寫InnoDB儲存引擎, 開銷大, 加鎖慢; 會出現死鎖; 鎖定粒度最小, 發生鎖衝突的概率最低, 併發度也最高
  • InnoDB與MyISAM的最大不同有兩點 : 一是支援事務(TRANSACTION); 二是採用了行級鎖
  • 索引失效會導致行鎖變成表鎖, 最常見的情況, varchar欄位沒寫引號
  • 可以使用SELECT xxx for update手動鎖定一行, 在鎖定某一行後, 其他的操作會被阻塞, 直到鎖定行的會話提交commit;

行鎖分析

  • 通過檢查InnoDB_row_lock狀態變數來分析系統上行鎖的爭奪情況

  • 使用命令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 : 系統啟動後到現在總共等待的次數;

    對於這5個狀態變數, 比較重要的是**InnoDB_row_lock_time_avg(等待平均時長), InnoDB_row_lock_waits (等待總次數), InnoDB_row_lock_time(等待總時長)**這三項

    尤其當等待次數很高, 而且每次等待時長也不小的時候, 我們就需要分析系統中為什麼會有如此多的等待, 然後根據分析結果著手製定優化計劃。

優化建議

  • 儘可能讓所有的資料檢索都通過索引來完成, 避免無索引行鎖升級為表鎖
  • 合理設計索引, 儘量縮小鎖的範圍
  • 儘可能減少檢索條件, 避免間隙鎖
  • 儘量控制事務大小, 減少鎖定資源量和時間長度
  • 儘可能低級別事務隔離

間隙鎖

定義 :

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

危害 :

因為查詢執行過程中通過範圍查詢的話, 會鎖定整個範圍內所有的索引值, 即使這個簡直並不存在。間隙鎖有一個比較致命的弱點, 就是當鎖定一個範圍鍵值之後, 即使某些不存在的鍵值也會被無辜的鎖定, 而造成在鎖定的時候無法插入鎖定鍵值範圍內的任何資料。在某些場景下這可能會對效能造成很大的危害。

間隙鎖演示:

1538463128427

頁鎖

  • 開銷和加鎖時間介於表鎖和行鎖之間;
  • 會出現死鎖
  • 鎖定粒度介於表鎖和行鎖之間, 併發度一般
  • 簡單瞭解即可