高併發情況下,MYSQL的鎖等待問題分析和解決方案

問題描述

在進行高併發性能調優的時候發現瞭如下的一個問題:

1. 在一個事務中同時包括了SELECT,UPDATE語句

2. SELECT和UPDATE涉及到的數據爲同一張表中的同一記錄

3. 在併發爲10的情況下就會觸發數據庫鎖等待和死鎖的情況

問題分析

在問題分析之前引入幾個概念

事務隔離級別

參考文章《事務的ACID特性》

共享鎖(S鎖)

SELECT 語句時對查詢行加的鎖類型爲共享鎖。

共享鎖的特性爲:不允許其他事務對該記錄加排他鎖,但是允許加共享鎖。

保持時間:可重複度級別中共享鎖會保持到事務結束。

排他鎖(X鎖)

MYSQL的默認隔離級別(可重複度)中,UPDATE,INSERT和DELETE語句對操作語句加的鎖類型爲排他鎖

排他鎖的特性爲:不允許其他事務對該記錄加共享鎖和排他鎖

保持時間:會保持到事務結束。

更新鎖(U鎖)

UPDATE語句在更新前需要對整表上更新鎖,在找到記錄後對需要操作記錄上排他鎖並釋放更新鎖

更新鎖特性爲:用來預定要對此頁施加排他鎖,它允許其他事務加共享鎖,但不允許再施加更新鎖或排他鎖

保持時間:會保持到事務結束。

分析

在MYSQL中使用的默認隔離接級別爲可重複讀,那麼SELECT語句在執行時會給記錄增加共享鎖,UPDATE語句會給數據上更新鎖和排他鎖,INSERT語句會給數據上排他鎖(數據爲新增,在事務結束之前是對其他事務不可見的,可忽略)。

這樣我們可以很清晰的看出,假設當前並行執行兩個事務A和B。

1. 當A開始執行事務中的SELECT語句時,會給該條記錄加共享鎖,這樣事務B不能夠對該記錄加排他鎖,需要等待A事務提交

2. 當A開始執行事務中的UPDATE語句時,首先會給該頁記錄加更新鎖,這樣事務B不能夠對該頁記錄加排他鎖,需要等待A事務提交;同時在定位記錄後給記錄增加排他鎖,這樣事務B不能對該記錄加共享鎖和排他鎖,需要等待A事務提交。

3. 由於A事務執行時間過長,在整個執行事務中還存在調用其他服務,查詢其他表的操作。導致事務提交時間過長,B事務一直等待,導致B事務鎖等待時間過長。引起文章標題中的問題。

解決方案

方案一:縮小事務範圍,只把DML語句(UPDATE,INSERT,DELETE)包裹在事務中

方案二:儘可能減少事務中包含的DML語句。提高事務的執行時間。

注意

1. Mybatis會再插入或刪除後,進行更新操作時使用同一個sqlSession,查詢時新建sqlSession。這樣先插入(刪除)後更新可以更新到新的數據(更新失敗);先插入(更新或者刪除)後查詢,則不會查詢到新的數據。參考《mysql同一個事務中先插入再查詢與先刪除再查詢結果分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章