資料庫 鎖分析

2021-10-06 21:02:08 字數 2802 閱讀 1195

mysql 中提供了兩種封鎖粒度:行級鎖以及表級鎖。

應該盡量只鎖定需要修改的那部分資料,而不是所有的資源。鎖定的資料量越少,發生鎖爭用的可能就越小,系統的併發程度就越高。

但是加鎖需要消耗資源,鎖的各種操作(包括獲取鎖、釋放鎖、以及檢查鎖狀態)都會增加系統開銷。因此封鎖粒度越小,系統開銷就越大。

在選擇封鎖粒度時,需要在鎖開銷和併發程度之間做乙個權衡。

1. 表鎖

開銷小,加鎖快;不會出現死鎖;鎖定力度大,發生鎖衝突概率高,併發度最低

分為兩種模式:

在表讀鎖和表寫鎖的環境下:讀讀不阻塞,讀寫阻塞,寫寫阻塞!

增加表鎖: lock table 表1 read/ write

釋放表鎖:onlock tables;

檢視加鎖的表: show open tables;

分析表鎖定的嚴重程度: show status like 『table%』

table_locks_immediate: 可立刻獲取的鎖數

table_locks_waited: 需要等待的表鎖數(該值越大,說明存在越大的鎖競爭)

建議:table_locks_immediate / table_locks_waited > 5000, 建議採用innodb引擎

2. 行鎖

開銷大,加鎖慢;會出現死鎖;鎖定粒度小,發生鎖衝突的概率低,併發度高

innodb實現了以下兩種型別的行鎖。

共享鎖(s鎖):讀鎖共享,會阻止其他事務獲得相同資料集的排他鎖。

排他鎖(x鎖):會阻塞其他的寫鎖和讀鎖。

注:innodb只有通過索引條件檢索資料才使用行級鎖,否則,innodb將使用表鎖。即innodb的行鎖是基於索引的!
事務可通過以下語句給記錄集加共享鎖或排他鎖。

共享鎖(s):select * from table_name where … lock in share mode

排他鎖(x):select * from table_name where … for update

3. 間隙鎖:gap locks:

給一條記錄加gap鎖只是不允許其他事務往這條記錄前邊的間隙插入新記錄。對於最後一條記錄之後的間隙,可以給索引中的最後一條記錄所在頁面的supremum記錄加上乙個gap鎖。

例如下面的建表語句:

create

table

`test`(

`id`int(11

)not

null,`

c`int(11)

default

null

primary

key(`id

`),key`c

`(`c

`))engine

=innodb;/

/插入資料

insert

into

tvalues(0

,0),

(5,5

),(10

,10);

如果用 select * from test for update 要把整個表所有記錄鎖起來,就形成了4個間隙,分別是 (-∞,0] 、 (0,5] 、 (5,10] 、 (10, +supremum] 。

若此時事務 a 執行 select * from test where id = 7 for update 語句,由於 id=7 這一行並不存在,因此會加上間隙鎖(5,10);

注:間隙鎖是在可重複讀隔離級別下才會生效。

4. next-key locks:

既想鎖住某條記錄,又想阻止其他事務在該記錄前邊的間隙插入新記錄,行鎖與gap locks相結合。

以下案例採用上面那個表,

案例:等值查詢:唯一索引

當事務a執行 update test set c = 2 where id = 9;

根據注1:加鎖範圍是(5,10],又因為這是乙個等值查詢,且id = 10 不滿足,所以根據注2,next-key lock 退化為間隙鎖 (5,10)。

5. 意向鎖

為了允許行鎖和表鎖共存,實現多粒度鎖機制,innodb提供兩種意向鎖:

6. 死鎖

死鎖必須具備以下四個條件:

互斥條件:該資源任意乙個時刻只由乙個執行緒占用。

請求與保持條件:乙個執行緒因請求資源而阻塞時,對已獲得的資源保持不放。

不剝奪條件:執行緒已獲得的資源在末使用完之前不能被其他執行緒強行剝奪,只有自己使用完畢後才釋放資源。

迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。

避免死鎖的幾種方式:

1)以固定的順序訪問表和行。比如對兩個job批量更新的情形,簡單方法是對id列表先排序,後執行,這樣就避免了交叉等待鎖的情形;將兩個事務的sql順序調整為一致,也能避免死鎖。

2)大事務拆小。大事務更傾向於死鎖,如果業務允許,將大事務拆小。

3)在同乙個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖概率。

4)降低隔離級別。如果業務允許,將隔離級別調低也是較好的選擇,比如將隔離級別從rr調整為rc,可以避免掉很多因為gap鎖造成的死鎖。

5)為表新增合理的索引。可以看到如果不走索引將會為表的每一行記錄新增上鎖,死鎖的概率大大增大。

Mysql資料庫鎖 表級鎖分析

按操作的型別分 讀鎖 共享鎖 針對同乙份資料,多個讀操作可以同時進行而不會相互影響。寫鎖 排它鎖 當前寫操作沒有完成,會阻斷其它的寫鎖和讀鎖。按對資料操作的粒度分 表鎖 偏讀 整個表被鎖,偏向於myisam引擎,開銷小,加鎖快,無死鎖 鎖定粒度大,發生鎖衝突的概率最高,併發度最低。行鎖 表級鎖分析 ...

資料庫(2)資料庫鎖

這一段時間一直在學習關係型資料庫,準備寫乙個小專題來總結一下這一段時間的學習結果。二.事物隔離等級和鎖的關係 網上很多部落格都是直接說了一連串的鎖,什麼悲觀鎖樂觀鎖,什麼讀寫鎖,什麼排他鎖共享鎖。說的不僅語焉不詳,而且分類紊亂,希望看到這篇文章能幫助你理清思路。從鎖的實現方式來看,鎖可以分為悲觀鎖和...

資料庫樂觀鎖和悲觀鎖例子和分析

1.樂觀鎖 樂觀地認為每次讀資料別人都不會修改,所以不需要用資料庫鎖 查出商店中id 1的商品的版本號 select version currentversion from shop where id 1 把id 1的商品庫存減1,並把版本號自增1 update shop set num num 1...