MySQL中有幾種類型的鎖?
鎖粒度來分,有表鎖、頁鎖和行鎖。
加鎖機制劃分,有樂觀鎖和悲觀鎖。
按兼容性劃分,有共享鎖和排他鎖。
按鎖模式劃分,有記錄鎖,間隙鎖,next-key鎖,意向鎖、插入意向鎖
全局鎖了解嗎??
全局鎖是對整個數據庫實例加讀鎖,整個數據庫處于只讀狀態,所有寫操作被阻塞,直到全局鎖被釋放。
使用場景是全庫備份,或者數據遷移時,使用全局鎖來保證數據的一致性。
-- 鎖定整個數據庫
FLUSH TABLES WITH READ LOCK;-- 執行備份操作
-- 例如使用 mysqldump 進行備份
! mysqldump -u username -p database_name > backup.sql-- 釋放全局鎖定
UNLOCK TABLES;
表鎖了解嗎?
常見于MyISAM引擎,InnoDB可以通過LOCK TABLES加鎖
適合讀多寫少,全表掃描和表結構變更時使用。
表鎖也分為共享鎖(讀鎖),排他鎖(寫鎖)。
MyISAM在指向SELECT操作時會自動加讀鎖,UPDATE/DELETE/INSERT的時候會自動加寫鎖
對于 InnoDB 引擎,無索引的?UPDATE/DELETE
?只能先進行全表掃描,可能會導致鎖大量行被鎖定,類似于表鎖。
ALTER TABLE會加排它鎖
說說MySQL的行鎖??
InnoDB中最細粒度的鎖,鎖定表中的一行記錄,允許其他事務訪問表中的其他行。
有索引的情況下,通過索引只鎖滿足條件的行;無索引的情況下,全表遍歷,遍歷一行就加一行行鎖,最差的情況會鎖定所有行,直到事務完成才會釋放所有行鎖。
行鎖又可以細分為記錄鎖,間隙鎖和臨鍵鎖。
通過SELECT .... FOR UPDATE可以加排它鎖。
通過SELECT .... IN SHARE MODE可以加共享鎖。?
select for update有什么需要注意的?
- 必須在事務中使用,否則鎖會立即釋放。
- 使用時注意是否命中索引,否則可能會鎖大量行。
說說記錄鎖
記錄鎖是行鎖的最基本的表現形式,當我們使用唯一索引或者主鍵索引進行等值查詢并顯式指定FOR UPDATE的時候,MySQL會為該行添加排它鎖類型的記錄鎖,禁止其他行讀取或修改記錄。
?注意使用非主鍵索引進行UPDATE時的鎖定路徑:輔助索引 → 主鍵索引
間隙鎖了解嗎?
范圍查詢或者不存在的記錄查詢時,用于鎖定記錄之間的間隙,防止其他事務在范圍中插入新紀錄,在可重復讀的事務隔離級別下生效,主要為了防止幻讀現象。
臨鍵鎖了解嗎?
臨鍵鎖就是間隙鎖+記錄鎖,鎖住記錄以及記錄之前的間隙,左開右閉,范圍查詢時生效。
當使用唯一索引的等值查詢匹配到一條記錄時,臨鍵鎖會退化成記錄鎖;如果沒有匹配到任何記錄,會退化成間隙鎖。
意向鎖是什么?
意向鎖是一種表級鎖,表示事務打算對表中的某些行數據加鎖,但是不會先直接鎖定行數據本身。
由InnoDB自動管理,當事務需要添加行鎖時,會先在表上添加意向鎖。這樣當另一個事務要添加表鎖的時候,可以通過查看表上的意向鎖,快速判斷表級鎖與現有行鎖的沖突,避免逐行掃描。
當執行SELECT?.... LOCK IN SHARE MODE的時候,會自動添加意向共享鎖;當執行 SELECT .... FOR UPDATE的時候,會自動添加意向排他鎖。
意向鎖之間相互兼容,也不會和行鎖沖突。
當前鎖 | IS | IX | S(表級) | X(表級) |
---|---|---|---|---|
IS | ? | ? | ? | ? |
IX | ? | ? | ? | ? |
S(表級) | ? | ? | ? | ? |
X(表級) | ? | ? | ? | ? |
MySQL的樂觀鎖和悲觀鎖了解嗎??
悲觀鎖是一種"先上鎖再操作"的保守策略,它假設數據被外界訪問時必然會產生沖突,因此在數據處理過程中全程加鎖,保證同一時間只有一個線程可以訪問數據。MySQL 中的行鎖和表鎖都是悲觀鎖。
樂觀鎖會假設并發操作不會總發生沖突,屬于小概率事件,因此不會在讀取數據時加鎖,而是在提交更新時才檢查數據是否被其他事務修改過。常見的實現方式有版本號機制和時間戳機制。通過在表中增加 version 字段或者 timestamp 字段來實現。
如何通過樂觀鎖和悲觀鎖解決庫存超賣的問題?
悲觀鎖通過?SELECT ... FOR UPDATE
?在查詢時直接鎖定記錄,確保其他事務必須等待當前事務完成才能操作該行數據。
樂觀鎖通過在表中增加 version 字段作為判斷條件。
有遇到過MySQL的死鎖問題嗎?是如何解決的?
MySQL的死鎖問題是多個事務同時持有資源并且相互等待對方的資源釋放引起的。訪問相同的資源,但順序不同,就會導致死鎖。我用SHOW ENGINE INNODB STATUS查看死鎖信息,發現是加鎖順序不一致導致的死鎖問題,調整加鎖順序之后恢復正常。