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...