1、事務的相關概念和整合過程就不在這裡重複,可看本人另一篇
2、這次主要是探索併發中資料的問題,場景是電商系統下單減庫存,mysql,暫沒涉及分布式和集群
3、所有測試我們先預設原商品庫存為100,且我們通過使用者不同來指定休眠更好的看效果,admin為休眠的使用者它下單1個商品,另乙個請求下單3個商品
@transactional(rollbackfor = exception.class,isolation = isolation.read_uncommitted)
@override
public boolean checkandlockstock(mapgoodsmap, string orderid)
listlogs = lists.newarraylist();
for(map.entryentry:goodsmap.entryset())
if("admin".equals(securityutil.getcurruser().getusername())) catch (interruptedexception e)
// throw busines***ception.of(businessmessageenum.e_error);
} if(!result)
} return true;
}
首先是admin請求先發,然後更新後不提交事務,進入休眠,接著另乙個使用者請求過來發現讀到的資料已經是admin沒提交的事務的資料,如果在休眠後讓admin那個執行緒回滾,髒讀就出現了
把隔離級別改一下就可以了
隔離級別為 read_committed 髒讀沒了,但是在admin請求過來後更新了資料但不提交事務,另乙個請求過來一陣操作並更新了資料提交事務,然後admin休眠到了才提交事務,結果另乙個請求東西沒了,本來結果應該是去掉 3+1,為96,但資料庫結果是99,也就是前面先提交事務的減3不見了
改級別
@transactional(rollbackfor = exception.class,isolation = isolation.repeatable_read)
事務a先查詢後更新,不提交事務,此時有寫鎖,事務b來查詢後再更新,阻塞,等a先提交事務之後b才能更新
事務a先查詢後休眠,此時不會鎖,事務b來查詢後再更新,提交事務,a更新再提交事務
repeatable_read 是在寫的時候給該條資料加鎖,前面更新的事務沒提交後面的事務是提交不了因為資料被鎖住了。 這個級別保證的就是修改資料的提交順序
實際上比如減少庫存在這個repeatable_read 隔離級別下還出現資料錯亂是因為在業務先查詢之後計算,再儲存計算的值有問題,它保證的是你寫完的資料不丟失,而不是保證你讀完到寫完,比如我一開始用的
integer before = goods.getstock();
integer after = before - entry.getvalue();
goods.setstock(after);
boolean result = this.updatebyid(goods);
而更新的順序其實是沒問題的,假如自己寫sql用 update t_mall_goods set stock = stock - # where id = # ,保證順序性之後拿最新的值而不是預先計算好,則沒問題。
那假如我們沒有這個順序性呢,就導致a更新後還沒提交,b更新後沒有限制直接提交,那a剛才update拿的即使是最新值也沒用,那個最新值在b更新之前的,結果就是b的更新沒有了
上面說到 repeatable_read不保證讀完到寫完,serializable 便可以,最嚴格的老師,只要它讀過,別人就只能讀不能寫,就相當於我看你一眼你就是我老婆,剩下的別人只能看不能動了,得等到我放你自由
用 repeatable_read 解決,是加寫鎖,這在商品裡會帶來的問題,下訂單整個事務可能涉及多個商品,而如果兩個請求各鎖住乙個商品,各自等對方的事務提交,就死鎖了。
@transactional(rollbackfor = exception.class,isolation = isolation.repeatable_read)
@override
public boolean checkandlockstock()
if("general".equals(securityutil.getcurruser().getusername()))
for(map.entryentry:goodsmap.entryset())
try catch (interruptedexception e)
if(!result)
} return true;
}
上面故意讓兩個訂單下兩個相同商品,但是相互執行順序調換,結果
實際上這種問題之所以出現因為我是單個商品更新的,如果商品是批量更新,儘管底層還是一條條執行,但這個時間差很小,沒有在業務層一條條更新這麼大的時間差,就基本不會有這種在業務層出現死鎖的問題。
其實我這裡是為了看效果用了linkedhashmap按照我們存入的順序,實際上用hashmap,儲存不按我們的順序再hash之後,儲存重疊的商品讀取出來前後順序都是一致的。但如果用的其它結構比如直接商品實體的list之類的,就需要注意這個死鎖問題。
如果希望自己讀完到寫完的過程中在業務層進行計算又能最後資料保持一致,可以使用下面的幾種方式
1、**鎖:這種就是簡單粗暴,**上加 synchronized 鎖
2、悲觀鎖:這種就是用前先鎖住,其他人等著
記一次版本併發開發過程
本週主要進行了1.1.1,1.1.2 與1.1.1合併發布 1.2.0三個版本的並行開發。本週發生了以下較嚴重的問題 問題一 1.1.1版本延期3天發布,原計畫3月5日發布,後改期到3月8日發布。主要原因 1 yy商品資料量加大,xx服務效能差,制定1.1.1版本計畫時,沒有充分考慮到這個問題 2 ...
一次事務過程
第二篇 一次事務過程 對於開發人員來說,我們經常做的是啟動乙個事務,執行sql,提交事務。這就完成了我們的工作。但是,就在這些簡單的動作背後,網路和資料庫都做了些什麼呢。我們都想知道。下面以乙個例項來說明。背景 使用者正執行乙個連線到oracle資料庫的客戶端應用程式,是乙個員工檔案管理程式。過程 ...
記一次5000併發的除錯過程
為了滿足招標和使用者的需要,希望公司的基礎架構能支援5000併發,特此進行驗證和除錯。向兄弟部門借了兩台伺服器 每台8核cpu,48g記憶體 在兩台伺服器上安裝虛擬化平台exsi,每台上安裝4個linux7.0虛擬機器,總共8個linux7.0虛擬機器 a伺服器上的四台虛擬機器 aa1,aa2,aa...