上面的一節總結了一下全局鎖/表鎖,這次講行鎖
Mysql支持行鎖是有引擎InnoDB實現的,MylSAM不支持行鎖,所以在操作業務時會鎖住整個表,那這樣出現併發的情況就大大擴大了。java編程的時候,我們有鎖範圍最小原則,不必要的數據不要加鎖,但是表鎖會鎖定整個表內容,所以不適合高併發的情況。
數據行鎖的意識就是在需要的數據行上加鎖,
比如下面這條語句
update t1 set age = 18 where name = 'lisan'
InnoDB會在lisan這條記錄上加鎖,不會鎖住整個t1表
這樣的話,併發的範圍就大大縮減了,執行update t1 set age=22 where name = 'wanger'的操作就不會被阻塞。
需要注意的點:
跟redoLog/binLog的兩階段提交一樣,鎖也分爲兩階段
1:在需要的時候獲取鎖
2:在commit之後統一釋放鎖。
例子 :sessionA執行了兩個操作
begin:
update t1 set age = 18 where name = 'zhangsan';
update t2 set address = 'heihei' where name = 'zhangsan';
commit;
sessionB如果在想執行查詢操作
select * from t1 where name = 'zhangsan';
必須等到sessionA的commit操作,所以現實業務中經常會出現這種情況。
圖書商城 BookA促銷,有很多人要購買,小明和小黑都是搶購用戶。
基本操作
begin:
-- 小黑賬戶扣錢;
update account set account = account-10 where name = '小黑';
-- 商城書數量-1;
update book set num = num-1 where name = 'bookA';
commit;
類似小明也要執行該操作,這個時候我們要注意,因爲 book表會被大量用戶訪問,所以該表的鎖時間要儘量的短,根據兩階段鎖的定義,在需要的時候獲取鎖,那麼我們就要在編程的時候特別注意:
有大併發場景的數據要放在最後獲取鎖。
儘管有上面的注意事項,我們還是會出現死鎖的情況,對於這樣的情況,可以開啓死鎖檢測,但是一定要注意控制併發度,在業務場景中,不能有過多的併發請求同時訪問一條數據,保證死鎖檢測的線程足夠小。