摘要:在層常用的悲觀鎖實現方式是加一個排他鎖。所以為了防止更新丟失可以在時加上加鎖這樣就可以阻止其余事務的但注意無法阻止這樣在操作提交前操作無法獲得排他鎖,從而避免對的重復更新導致的更新丟失。
更新丟失是指并發下兩次更新同時進行,后一次更新覆蓋了前一次更新的情況,更新丟失是數據沒有保證一致性導致的。
舉個栗子:
用戶A在銀行卡有100元錢,某一刻用戶B向A轉賬50元(稱為B操作),同時有用戶C向A轉賬50元(稱為C操作);
B操作從數據庫中讀取他此時的余額100,計算新的余額為100+50=150
C操作也從數據庫中讀取他此時的余額100,計算新的余額為100+50=150
B操作將balance=150寫入數據庫,之后C操作也將balance=150寫入數據庫
最終A的余額變為150
上面的例子,A同時收到兩筆50元轉賬,最后的余額應該是200元,但卻因為并發的問題變為了150元,原因是B和C向A發起轉賬請求時,同時打開了兩個數據庫會話,進行了兩個事務,后一個事務拿到了前一個事務的中間狀態數據,導致更新丟失。
常用的解決思路有兩種:
加鎖同步執行
update前檢查數據一致性
悲觀鎖顧名思義,悲觀鎖在讀取數據的時候都會認為會有別人去修改,于是在取數據的時候會對當前數據加一個鎖,在操作結束前,不允許其余操作更改。要注意悲觀鎖和樂觀鎖都是業務邏輯層次的定義,不同的設計可能會有不同的實現。在mysql層常用的悲觀鎖實現方式是加一個排他鎖。
排他鎖
查閱資料很多對排他鎖的解釋是:“排他鎖通過在事務中使用select xx for update語句來實現,排他鎖會在當前行加一個行級鎖,在當前事務提交前,其余事務無法進行update操作。”
然而實際上并不是這樣,實際上是加了排他鎖的數據,在釋放鎖(事務結束)之前其他事務不能再對該數據加鎖
排他鎖之所以能阻止update,delete等操作是因為update,delete操作會自動加排他鎖
也就是說即使加了排他鎖也無法阻止select操作。而select XX for update 語法可以對select 操作加上排他鎖。所以為了防止更新丟失可以在select時加上for update加鎖 這樣就可以阻止其余事務的select for update(但注意無法阻止select)
example:
begin; select * from account where id = 1 for update; update account set balance=150 where id =1; commit;
這樣在B操作提交前,C操作無法獲得排他鎖,從而避免對account的重復更新導致的更新丟失。
樂觀鎖樂觀鎖是指在獲取數據時候不加鎖,樂觀的認為操作不會有沖突,在update的時候再去檢查沖突。
example:
begin; select balance from account where id=1; -- 得到balance=100;然后計算balance=100+50=150 update account set balance = 150 where id=1 and balance = 100; commit;
如上,如果sql在執行的過程中發現update的affected為0 說明balance不等于100即該條數據有被其余事務更改過,此時業務上就可以返回失敗或者重新select再計算
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17670.html
摘要:也就是說當使用字符型存儲數據后,該數據轉換為二進制時的長度超過了位,那么該數據將不會完整存儲,會丟失一部分數據。 showImg(https://segmentfault.com/img/bVbuYxg?w=3484&h=2480); 閱讀本文大約需要 8 分鐘。 寫在前面 數據庫打算只寫 MySQL,Redis 兩部分,不會很細,主要以面試題為主。這次寫的是 MySQL 篇。 1.說...
閱讀 2591·2021-09-26 10:17
閱讀 3220·2021-09-22 15:16
閱讀 2130·2021-09-03 10:43
閱讀 3257·2019-08-30 11:23
閱讀 3657·2019-08-29 13:23
閱讀 1301·2019-08-29 11:31
閱讀 3686·2019-08-26 13:52
閱讀 1394·2019-08-26 12:22