MySQL 全域性鎖和表鎖

邢闖洋發表於2021-05-26

MySQL 的鎖可以分為三大類

  • 全域性鎖
  • 表鎖
  • 行鎖

全域性鎖

  • 對整個資料庫例項加鎖
  • 命令是 Flush tables with read lock (FTWRL) 當你讓整個資料庫處於只讀狀態,可以用這個,之後其他執行緒的所有增刪改操作都會被阻塞,包括建表,修改表結構

應用場景

  • 典型場景是做全庫邏輯備份,確保不會有其他執行緒運算元據,但是帶來的危險就是業務停擺

mysqldump

  • 官方自帶的 mysqldump 使用引數 –single-transaction 時會啟動一個事務,這個事務隔離級別為可重複讀,確保拿到了一致性檢視,就可以安心備份資料了,也不會影響業務
  • 但是資料庫引擎必須是 InnoDB

表鎖

mysql 表鎖有兩種

  • 表鎖
  • 後設資料鎖(meta data lock,MDL)

表鎖的語法是

lock tables … read/write

主動釋放鎖的語法

unlock tables;

對錶加讀鎖後,自己也不能對其進行修改;自己和其他執行緒只能讀取該表。 當對某個表執加上寫鎖後(lock table t2 write),該執行緒可以對這個表進行讀寫,其他執行緒對該表的讀和寫都受到阻塞;

行鎖

mysql 行鎖是由引擎層實現的,並不是所有引擎都支援行鎖,MyISAM 不支援行鎖

兩階段鎖

在 InnoDB 事務中,行鎖是在需要的時候才加上的,但並不是不需要了就立刻釋放,而是要等到事務結束時才釋放。這個就是兩階段鎖協議。
知道了這個設定,在編寫程式碼中有關於事務的地方,如果你的事務中需要鎖多個行,要把最可能造成鎖衝突、最可能影響併發度的鎖儘量往後放。

死鎖和死鎖檢測

當併發系統中不同執行緒出現迴圈資源依賴,涉及的執行緒都在等待別的執行緒釋放資源時,就會導致這幾個執行緒都進入無限等待的狀態,稱為死鎖。
如我們開啟了兩個事務,事務A中 update t1 set k=k+1 where id=1,事務B 中 update t1 set k=k+1 where id=1
這時候,事務 A 在等待事務 B 釋放 id=2 的行鎖,而事務 B 在等待事務 A 釋放 id=1 的行鎖。 事務 A 和事務 B 在互相等待對方的資源釋放,就是進入了死鎖狀態

兩種策略

  • 直接進入等待,直到超時,超時時間引數設定為 innodb_lock_wait_timeout
  • 發起死鎖檢測,innodb_deadlock_detect 設定為 on 表示開啟檢測,發現死鎖後,主動回滾某個事務,讓另一個事務順利執行。
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章