MySQL 全局鎖、表級鎖、行級鎖,你搞清楚了嗎?

大家好 , 我是小林 。
最近重新補充了《MySQL 有哪些鎖》文章內容:

  • 增加記錄鎖、間隙鎖、net-key 鎖
  • 增加插入意向鎖
  • 增加自增鎖為 innodb_autoinc_lock_mode = 2 模式時 , 為什么主從環境會有不安全問題的說明
所以 , 現在內容還是比較全面的 , 基本把 MySQL 用到的鎖都說了一遍 , 大家可以在復習復習 。
這次 , 來說說 MySQL 的鎖 , 主要是 Q&A 的形式 , 看起來會比較輕松 。
不多 BB 了 , 發車!
在 MySQL 里 , 根據加鎖的范圍 , 可以分為全局鎖、表級鎖和行鎖三類 。
MySQL 全局鎖、表級鎖、行級鎖,你搞清楚了嗎?

文章插圖
全局鎖
全局鎖是怎么用的?
要使用全局鎖 , 則要執行這條命:
flush tables with read lock執行后 , 整個數據庫就處于只讀狀態了 , 這時其他線程執行以下操作 , 都會被阻塞:
  • 對數據的增刪改操作 , 比如 insert、delete、update等語句;
  • 對表結構的更改操作 , 比如 alter table、drop table 等語句 。
如果要釋放全局鎖 , 則要執行這條命令:
unlock tables當然 , 當會話斷開了 , 全局鎖會被自動釋放 。
全局鎖應用場景是什么?
全局鎖主要應用于做全庫邏輯備份 , 這樣在備份數據庫期間 , 不會因為數據或表結構的更新 , 而出現備份文件的數據與預期的不一樣 。
舉個例子大家就知道了 。
在全庫邏輯備份期間 , 假設不加全局鎖的場景 , 看看會出現什么意外的情況 。
如果在全庫邏輯備份期間 , 有用戶購買了一件商品 , 一般購買商品的業務邏輯是會涉及到多張數據庫表的更新 , 比如在用戶表更新該用戶的余額 , 然后在商品表更新被購買的商品的庫存 。
那么 , 有可能出現這樣的順序:
  1. 先備份了用戶表的數據;
  2. 然后有用戶發起了購買商品的操作;
  3. 接著再備份商品表的數據 。
也就是在備份用戶表和商品表之間 , 有用戶購買了商品 。
這種情況下 , 備份的結果是用戶表中該用戶的余額并沒有扣除 , 反而商品表中該商品的庫存被減少了 , 如果后面用這個備份文件恢復數據庫數據的話 , 用戶錢沒少 , 而庫存少了 , 等于用戶白嫖了一件商品 。
所以 , 在全庫邏輯備份期間 , 加上全局鎖 , 就不會出現上面這種情況了 。
加全局鎖又會帶來什么缺點呢?
加上全局鎖 , 意味著整個數據庫都是只讀狀態 。
那么如果數據庫里有很多數據 , 備份就會花費很多的時間 , 關鍵是備份期間 , 業務只能讀數據 , 而不能更新數據 , 這樣會造成業務停滯 。
既然備份數據庫數據的時候 , 使用全局鎖會影響業務 , 那有什么其他方式可以避免?
有的 , 如果數據庫的引擎支持的事務支持可重復讀的隔離級別 , 那么在備份數據庫之前先開啟事務 , 會先創建 Read View , 然后整個事務執行期間都在用這個 Read View , 而且由于 MVCC 的支持 , 備份期間業務依然可以對數據進行更新操作 。

經驗總結擴展閱讀