問題描述:
mysql 數據庫丟失更新的定義:(其實在數據庫角度都不會產生丟失更新的問題,問題的源頭應用程序邏輯更新的問題)
1. 事務1 查詢一行數據放在本地緩存,並且顯示給用戶user1 -->select balance from account where user= 'a' ;
2. 事務2 查詢同樣的一行數據放在本地緩存,並且顯示給用戶user2 -->select balance from account where user= 'a' ;
3. 用戶user1修改這條數據,並且更新提交數據庫 --> update account set balance = balance -100 where user= 'a' ;
4. 用戶user2修改顯示的數據,並且更新提交數據庫 --> update account set balance = balance -800 where user= 'a' ;
顯然上面user1 更新的數據丟失了,這也是更新覆蓋,比如用戶轉賬的操作。a 賬戶總共1000,事務1和事務2查詢賬戶都是1000,然后事務1賬戶扣減100,提交。事務2扣減800提交。這時候賬戶余額為200,事務1扣減的100 會不翼而飛,實際上應該剩下100,這會導致嚴重的問題。
-------------------------------------------------------------------
-------------------------------------------------------------------
-------------------------------------------------------------------
暫時想到兩種解決辦法:
解決辦法1:使用悲觀鎖
1)讀取鎖定 --> select balance from account where user= 'a' for update
2)更新 --> update account set balance = balance -100 where user= 'a'
解決辦法2: 使用樂觀鎖
1)表增加字段 jpa_version int 版本號 --> select balance,version from account where user= 'a'
2) 使用版本號更新 --> update account set balance = balance -100 where user= 'a' and jpa_version = ${version}
解決辦法3:
1) 驗證未修改前的金額是否一致--> update account set balance = 100 where user= 'a' and balance = $old_balance
總結:
對於賬戶交易建議直接使用悲觀,數據庫的性能很高,並發度不是很高的場景兩者性能沒有太大差別。如果是交易減庫存的操作可以考慮樂觀鎖,保證並發度。