- Q1 : MySQL有哪些鎖,功能是什么,如何項目中使用?
- Q2 : 行鎖是如何實現的?什么情況下會使用行鎖?
- Q3 : 四種事務隔離形式的行鎖有什么不一樣?
- 讀未提交
- 讀提交
- 可重復讀
- 串行
- Q4 : MySQL 的讀寫都是怎樣加鎖的?
- Q5 : 需要注意什么?
Q1 : MySQL有哪些鎖,功能是什么,如何項目中使用?
- 全局 - 鎖定全局(庫)的數據,所有寫全部阻塞,只能寫.
- 只有做全庫邏輯備份才會用
- 表鎖 - 鎖定一個表的數據,避免數據更新時的并發問題
- 行鎖 - 鎖定某一行/一個區間(間隙)的數據,避免數據更新時的并發問題
- 行鎖是通過索引實現的,如果沒有索引,那么將會使用表鎖.
Q2 : 行鎖是如何實現的?什么情況下會使用行鎖?
- MySQL 如何加表鎖:
- 直接在整個表上加鎖,限制全表的讀寫訪問(鎖全表)
那么行鎖是如何工作的呢?
行鎖是通過索引實現的,主要分為兩個階段
-
二級索引(間隙/臨建)加鎖并命中數據(主鍵 id)
- 加鎖方式: 先根據邊界條件或者等值條件命中情況決定加鎖的范圍
- 沒命中: 索引無法命中不存在的 key,但是要避免數據在(事務)執行期間新數據的加入導致數據混亂問題,就會在未命中前后 key 區間加間隙鎖,保證執行期間沒有數據插入
- 其他: 如果鎖范圍查詢就會對查詢范圍進行加鎖,在結合剛剛的未命中區間,就是二級索引加鎖的區間
- 作用: 限制區間的數據插入,避免區間內數據的插入導致結果錯誤問題
- 加鎖方式: 先根據邊界條件或者等值條件命中情況決定加鎖的范圍
-
主鍵索引加鎖
- 根據上面二級索引命中的主鍵 id,對每個 id 的數據行進行加鎖
- 作用: 避免事務執行期間數據被修改
Q3 : 四種事務隔離形式的行鎖有什么不一樣?
讀未提交
有的人說讀提交不會顯示加鎖,我覺得不加鎖不科學,不加鎖百分百會出現讀寫并發沖突問題,一定會報錯;
但是 MySQL 不會做一個有問題的東西給大家用,那為什么讀未提交不會阻塞其他事務,我想只有一個解釋鎖的生命周期(持有時間)
- 鎖持有時間是任務結束(并不是事務結束),不會加間隙鎖
- 優點: 鎖持有時間短,對其他事務影響小
- 缺點: 臟讀問題
讀提交
- 鎖的生命周期鎖整個事務,不會加間隙鎖
- 優點: 沒有間隙鎖,對其他事務(在間隙的數據插入)性能影響小
- 缺點: 數據幻讀問題
(思考: 有鎖的話讀提交還有不可重復讀的問題嗎?)
可重復讀
- 鎖的生命周期鎖整個事務,會加間隙鎖
- 優點: 避免數據幻讀
- 缺點: 略微降低數據寫入的性能
串行
- 最嚴格的隔離級別,它通過加 范圍鎖 或 表鎖 來確保事務之間沒有沖突,所有讀取的數據都必須是其他事務已提交的數據。
- 由于避免了幻讀,它會在 查詢范圍 上加 間隙鎖 或 表鎖,防止其他事務在查詢范圍內插入或修改數據。
(我覺得串行不需要鎖,單線程的執行事務就沒有并發問題了呀,為什么需要鎖?搞不懂)
Q4 : MySQL 的讀寫都是怎樣加鎖的?
-
MySQL 的普通查詢是不會加鎖的,而是通過 mvcc 去進行多版本并發控制
-
MySQL 寫是通過鎖控制的,具體鎖的程度根據索引情況與隔離程度而定
Q5 : 需要注意什么?
- 沒有索引鎖全表
行鎖只有索引的條件下才會生效,沒有索引會鎖全表,造成其他線程阻塞,連接大量堆積,嚴重影響性能.
沒有索引的查詢與更新數據在并發情況下表現更差.
索引不僅會減少磁盤 io 的次數加快數據的查詢,還可以提高并發情況下的讀寫性能表現.
參考:
https://www.xiaolincoding.com/mysql/lock/how_to_lock.html#%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E8%8C%83%E5%9B%B4%E6%9F%A5%E8%AF%A2
https://juejin.cn/post/6931752749545553933
https://blog.csdn.net/weixin_43994761/article/details/132250415
https://blog.unclezs.com/pages/180d74/#%E7%AE%80%E4%BB%8B