前言
1)在數據庫的鎖機制中介紹過,數據庫管理系統(DBMS)中的並發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和一致性以及數據庫的一致性。
2)加鎖是為了解決更新丟失問題
更新丟失
兩次更新同時進行,后一次更新覆蓋了前一次更新的情況,更新丟失是數據沒有保證一致性導致的。
------事務A查詢余額,此時balance=100------- select balance from account where id = '1'; ------事務B查詢余額,此時balance=100------- select balance from account where id = '1'; ------事務A充值100,此時num=200------- update account set balance = balance + 100 where id = 1; ------事務B消費30,此時num=70------- update account set balance = balance - 30 where id = 1;
由於A、B是同時進行的,造成了事務A被事務B覆蓋了。
解決辦法
1)加鎖同步執行
2)update時檢查
樂觀並發控制(樂觀鎖)
1)假設數據不會發生沖突,只在提交操作時檢查是否違反數據完整性。
2)樂觀鎖一般是為數據增加一個版本標識實現。
------事務A查詢余額,此時balance=100,version=1------- select balance,version from account where = '1'; ------事務B查詢余額,此時balance=100,version=1------- select balance,version from account where id= '1'; ------事務A充值100,此時num=200------- update account set balance = balance + 100,version = version + 1 where id = 1 and version = 1; ------事務B消費30,此時失敗------- update account set balance = balance - 30,version = version + 1 where id = 1 and version = 1;
優點與不足
- 樂觀鎖在失敗回滾的開銷較大
悲觀並發控制(悲觀鎖)
1)假定數據會發生沖突,屏蔽一切可能違反數據完整性的操作。
2)悲觀鎖一般利用mysql的排它鎖實現。
------事務A查詢余額,此時balance=100並為id=1加鎖------- select balance from account where id = '1' for update; ------事務B查詢余額,此時無法加鎖失敗------- select balance from account where id = '1' for update; ------事務A充值100,此時num=200------- update account set balance = balance + 100 where id = 1;
優點與不足
- 悲觀鎖采用一鎖二查三更新的嚴謹策略。
- 加鎖產生額外的開銷,容易產生死鎖;
- 一個事務中鎖定了某行數據,其他事務將等待。