「MySQL高級篇」MySQL鎖機制 && 事務( 四 )

行鎖基本演示

  • 我們采用兩個客戶端,首先要關閉掉自動提交功能:set autocommit = 0;
    • 普通的select不加鎖,沒有什么影響
    • 而insert和update就不一樣了,會加排它鎖,其他客戶端陷入阻塞狀態,不能對該行(注意得兩個客戶端操作的是同一行,才會阻塞,因為是行鎖)進行修改,直到加鎖的客戶端提交完事務(相當于釋放鎖)

「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖

「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖
無索引行鎖升級為表鎖
如果不通過索引條件檢索數據,那么InnoDB將對表中的所有記錄加鎖,實際效果跟表鎖一樣 。

「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖
由于 執行更新時,name字段本來為varchar類型,我們是作為數組類型使用,存在類型轉換,索引失效,最終行鎖變為表鎖 ;(字符串類型,在SQL語句使用的時候沒有加單引號,導致索引失效,查詢沒有走索引,進行全表掃描,索引失效,行鎖就升級為表鎖)
InnoDB 行鎖爭用情況showstatus like 'innodb_row_lock%';
「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖
  • Innodb_row_lock_current_waits: 當前正在等待鎖定的數量
  • Innodb_row_lock_time: 從系統啟動到現在鎖定總時間長度
  • Innodb_row_lock_time_avg:每次等待所花平均時長
  • Innodb_row_lock_time_max:從系統啟動到現在等待最長的一次所花的時間
  • Innodb_row_lock_waits: 系統啟動后到現在總共等待的次數
當等待的次數很高,而且每次等待的時長也不小的時候,我們就需要分析系統中為什么會有如此多的等待,然后根據分析結果著手制定優化計劃 。
總結InnoDB存儲引擎由于實現了行級鎖定,雖然在鎖定機制的實現方面帶來了性能損耗可能比表鎖會更高一些 , 但是在整體并發處理能力方面要遠遠高于MyISAM的表鎖的 。當系統并發量較高的時候,InnoDB的整體性能和MyISAM相比就會有比較明顯的優勢 。
但是,InnoDB的行級鎖同樣也有其脆弱的一面,當我們使用不當的時候 , 可能會讓InnoDB的整體性能表現不僅不能比MyISAM高 , 甚至可能會更差 。
優化建議
  • 盡可能讓所有數據檢索都能通過索引來完成,避免無索引行鎖升級為表鎖 。
  • 合理設計索引,盡量縮小鎖的范圍 。
  • 盡可能減少索引條件 , 及索引范圍,避免間隙鎖 。
  • 盡量控制事務大??,减少锁定自嚧量和时间长?。
  • 盡可使用低級別事務隔離(但是需要業務層面滿足需求)
表級鎖擴展全局鎖
「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖
特點
「MySQL高級篇」MySQL鎖機制 && 事務

文章插圖
備份的一致性問題來看下邊這個場景 , 比如我們創建的購買操作,涉及到了用戶余額表+訂單表,流程順序如下:
  1. 當前正在備份用戶余額表,備份了小明同學的余額是100
  2. 此時小明剛好下了訂單 , 理應扣減50元
    1. 但由于用戶余額表已經備份完畢,余額表不會受到影響
  3. 小明下好單了,如今來備份訂單表了,能夠備份到小明剛下的單
到這里是否發現問題了,就是備份后的結果是:小明的余額沒扣錢 , 但卻有相關的訂單數據 , 出現了數據不一致的情況