Reference: http://blog.ruaby.com/?p=256html
相對於串行處理來講,併發事務處理能大大增長數據庫資源的利用率,提升數據庫系統的事務吞吐量,從而能夠支持更多的用戶。但併發事務處理也會帶來一些問題,主要包括如下幾種狀況:mysql
在上面講到的併發事務處理帶來的問題中,「更新丟失」一般是應該徹底避免的。但防止更新丟失,並不能單靠數據庫事務控制器來解決,須要應用程序對要更新的數據加必要的鎖來解決,所以,防止更新丟失應該是應用的責任。git
「髒讀」、「不可重複讀」和「幻讀」,其實都是數據庫讀一致性問題,必須由數據庫提供必定的事務隔離機制來解決。數據庫實現事務隔離的方式,基本上可分爲如下兩種:github
數據庫的事務隔離越嚴格,併發反作用越小,但付出的代價也就越大,由於事務隔離實質上就是使事務在必定程度上 「串行化」進行,這顯然與「併發」是矛盾的。同時,不一樣的應用對讀一致性和事務隔離程度的要求也是不一樣的,好比許多應用對「不可重複讀」和「幻讀」並不敏感,可能更關心數據併發訪問的能力。sql
InnoDB實現瞭如下兩種類型的行鎖。數據庫
對於UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X);對於普通SELECT語句,InnoDB不會加任何鎖;事務能夠經過如下語句顯示給記錄集加共享鎖或排他鎖。併發
用SELECT … IN SHARE MODE得到共享鎖,主要用在須要數據依存關係時來確認某行記錄是否存在,並確保沒有人對這個記錄進行UPDATE或者DELETE操做。可是若是當前事務也須要對該記錄進行更新操做,則頗有可能形成死鎖,對於鎖定行記錄後須要進行更新操做的應用,應該使用SELECT… FOR UPDATE方式得到排他鎖。htm
更多詳情參考:http://www.cnblogs.com/qq78292959/archive/2013/01/30/2883100.htmlblog
github項目地址:https://github.com/sanjiOP/seckill事務
按照正常的購買流程:查詢商品庫存,庫存大於0時,生成訂單,去庫存。若是出現併發,致使在查詢商品庫存的時候,庫存會一直出現大於0的狀況,出現超賣現象。
基於mysql的事務和鎖實現方式:
若是不開啓事務,第二步即便加鎖,第一個會話讀庫存結束後,變會釋放鎖,第二個會話仍有機會在去庫存前讀庫存,出現超賣。
若是開啓事務,第二步不加鎖,第一個會話讀庫存結束後,第二個會話容易出現【髒讀】,出現超賣。
即加事務,又加讀鎖:開啓事務,第一個會話讀庫存時加讀鎖,併發時,第二個會話也容許得到讀庫存的讀鎖,可是在第一個會話執行寫操做時,寫鎖便會等待第二個會話的讀鎖,第二個會話執行寫操做時,寫鎖便會等待第一個會話的讀鎖,出現死鎖
即加事務,又加寫鎖:第一個會話讀庫存時加寫鎖,寫鎖會阻止其它事務的讀鎖和寫鎖。直到commit纔會釋放,容許第二個會話查詢庫存,不會出現超賣現象。