程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> mysql的行鎖的另一種解決方案

mysql的行鎖的另一種解決方案

編輯:關於SqlServer

做項目時由於業務邏輯的需要,必須對數據表的一行或多行加入行鎖,舉個最簡單的例子,圖書借閱系統。假設id=1的這本書庫存為1,但是有2個人同時來借這本書,此處的邏輯為

Select restnum from book where id =1 ; -- 如果 restnum 大於 0 ,執行 update Update book set restnum=restnum-1 where id=1 ;

問題就來了,當2個人同時來借的時候,有可能第一個人執行select語句的時候,第二個人插了進來,在第一個人沒來得及更新book表的時候,第二個人查到數據了,其實是髒數據,因為第一個人會把restnum值減1,因此第二個人本來應該是查到id=1的書restnum為了,因此不會執行update,而會告訴它id=1的書沒有庫存了,可是數據庫哪懂這些,數據庫只負責執行一條條SQL語句,它才不管中間有沒有其他sql語句插進來,它也不知道要把一個session的sql語句執行完再執行另一個session的。因此會導致並發的時候restnum最後的結果為-1,顯然這是不合理的,所以,才出現鎖的概念,MySQL使用innodb引擎可以通過索引 對數據行加鎖。以上借書的語句變為:

Begin; Select restnum from book where id =1 for update ; -- 給 id=1 的行加上排它鎖且 id 有索引 Update book set restnum=restnum-1 where id=1 ; Commit; 這樣,第二個人執行到select語句的時候就會處於等待狀態直到第一個人執行commit。從而保證了第二個人不會讀到第一個人修改前的數據。
*****************************************************************************************************
文章的意思是想講行級鎖的應用,不過針對上面舉的那個例子的那個場景(其實這種場景還是經常出現的比如,秒殺系統等)完全可以用修改下sql語句即可。
update book set restnum=restnum-1 where id=1 and restnum>0;
只要在原來的update 語句之後加一個 restnum>0 ,問題即可解決

Begin; 
 
Select   restnum  from  book  where  id =1  for   update ;
Update   book  set restnum=restnum-1 where id=1 ;  

Commit;   

update book set restnum=restnum-1 where id=1 and restnum>0;
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved