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 協議》,轉載必須註明作者和本文連結