文章來源:51CTO博客,作者:青苔初生
一文讀懂所有鎖,了解他們的優缺點和使用場景。
表級鎖與行級鎖
表級鎖:
table-level locking,鎖住整個表。
開銷小,加鎖快。
不會死鎖(一次性加載所需的所有表)。
鎖粒度大,發生鎖沖突概率大,並發效率低。
適合查詢。
行級鎖:
row-level loking,鎖住一行記錄。
開銷大,加鎖慢。
會死鎖。
鎖粒度小,發生所沖突概率小,並發效率高。
適合並發寫,事務控制。
並不是直接丟記錄行加鎖,而是對行對應的索引加鎖:
如果sql 語句操作了主鍵索引,Mysql 就會鎖定這條主鍵索引。
如果sql語句操作了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相關的主鍵索引。
在InnoDB中,如果SQL語句不涉及索引,則會通過隱藏的聚簇索引來對記錄加鎖。
對聚簇索引加鎖,實際效果跟表鎖一樣,因為找到某一條記錄就得掃描全表,要掃描全表,就得鎖定表。
引擎與鎖:
MyISAM引擎支持表級鎖,不支持行級鎖。
InnoDB引擎支持表級鎖和行級鎖,默認為行級鎖。
共享鎖與排他鎖
共享鎖:
有稱之為S鎖、讀鎖。
當前線程對共享資源加共享鎖,其他線程可以讀取此資源、可以繼續追加共享鎖,但是不能修改此資源、不能追加排他鎖。
語法:select id from t_table in share mode;
多個共享鎖可以共存,共享鎖與排他鎖不能共存。
排他鎖:
又稱之為X鎖、寫鎖。
當前線程對共享資源加排他鎖,其他線程不允許讀取此資源,不允許追加共享鎖,不允許修改此資源,不允許追加排他鎖。
語法:
1. update t_table set a =1; // 數據庫的增刪改操作默認都會加排他鎖
2. select * from t_table for update;// for update也是一種增刪改
排他鎖是獨占的,不會與其他鎖共存。
樂觀鎖與悲觀鎖
樂觀鎖與悲觀鎖是邏輯上的鎖。
樂觀鎖:
樂觀鎖:樂觀地認為,並發問題很難發生。
樂觀鎖雖然認為並發問題很難發生,但並不是不會發生,所以也會有措施防止問題真的產生:每次數據修改都自增版本號version。
進行數據讀取時,並不加鎖,而是同時讀取當前的版本號version1;在對數據進行修改時,要判斷當前的版本號version2是否等於之前的版本號version1。
版本號不匹配,則代表着並發問題已產生,所以需要回滾此次操作。
實現方式:版本號機制、CAS。
悲觀鎖:
悲觀鎖:悲觀地認為,並發問題極易發生。
悲觀鎖認為並發問題極易發生,所以每次操作,無論讀寫,都會對記錄加鎖,以防止其他線程對數據進行修改。
實現方式:數據庫的行鎖、讀鎖和寫鎖。
最后,特別推薦一個分享C/C++和算法的優質內容,學習交流,技術探討,面試指導,簡歷修改...還有超多源碼素材等學習資料,零基礎的視頻等着你!
還沒關注的小伙伴,可以長按關注一下:
