hibernate之資料庫隔離機制與鎖
長久以來,對資料庫的各種隔離機制一直很模糊,總搞不清楚在別人眼裡很簡單的鎖機制,事務隔離機制,最近查了一些資料,把自己對資料庫的一些理解寫下來,權當筆記,不對的地方希望大家指正。
為了確保併發使用者在訪問同一資料庫物件時的正確性(即無丟失修改、可重複讀、不讀「髒」資料),資料庫中引入了鎖機制:
從資料庫角度來說,資料庫一般情況下會有以下兩種鎖型別:
1.排它鎖(x鎖):若事務t對資料d加x鎖,則其它任何事務都不能再對d加任何型別的鎖,直至t 釋放d 上的x 鎖;一般要求在修改資料前要向該資料加排它鎖,所以排它鎖又稱為寫鎖,被寫鎖鎖定的記錄可以被無鎖讀取,比如在oracle中沒有讀鎖的概念,在sqlserver中可以使用with nolock。
2.共享鎖(s鎖):若事務t對資料d加s 鎖,則其它事務只能對d加 s鎖,而不能加x 鎖,直至 t 釋放d 上的s 鎖;一般要求在讀取資料前要向該資料加共享鎖,所以共享鎖又稱為讀鎖。
說明:因為任務事務在讀取或者更改一條資料之前,都需要先申請相應的鎖型別,所以一旦加上寫鎖,則其它事務只能等待該事務完成後才能申請相應的鎖。一旦加上讀鎖(共享鎖),則別的事務還可以對相同的資料申請共享鎖,可以對資料進行讀取,則不能修改,無鎖讀取在sqlserver 中可以使用select ...from ....with nolock。在oracle沒有讀鎖概念。
其它鎖概念:
悲觀鎖:指對於外界對資料的修改持保守態度,為了保持資料被操作的一致性,於是對資料採取了資料庫層次的鎖定狀態,依靠資料庫提供的鎖機制來實現。該鎖只是基於以上資料庫提供的鎖實現。
樂觀鎖:與「悲觀鎖」正好相反,該鎖機制認為資料資料的訪問很少發生衝突,採取了寬鬆的鎖機制,一般情況下,樂觀鎖由開發者自行實現,一般情況下,開發者為資料庫需要樂觀鎖的表增加乙個版本字段或者時間戳字段,若記錄要修改,則增加該記錄的版本字段,在提交時與原資料進行比較,若大於則說明可以正常提交,否則說明該記錄已經被修改,需要進行檢查。時間戳也同樣。
悲觀鎖說明:比如事務t1通過sql語句"select user.name from user as user where user.id=1 for update"來查詢記錄,則此時滿足條件的記錄全部被鎖定,若事務t2通過sql語句「selct user.name from user where user.id=1 for update」,則事務t2只能等式待事務t1完成後才能執行。
在資料庫原理中,又可以把讀鎖和寫鎖分為長鎖和短鎖:
長鎖:在整個事務範圍內,該鎖都有效。比如事務t1中有對資料d1的長寫鎖,則表示在t1整個事務過程中,別的事務都無法取得對資料d1的更新許可權,直到事務t1完成提交或者回滾。
短鎖:只在資料查詢的更新等操作時有效,資料操作完畢馬上釋放。釋放完畢後,別的事務即可以申請對該資料的鎖。
謂詞鎖:鎖定滿足查詢條件
資料庫的標準隔離級別及鎖定義:
隔離級別
記錄上的寫鎖是長期的
記錄上的讀鎖是長期的
謂詞上的讀鎖和寫鎖是長期的
read uncommitted
否無讀鎖
無謂詞鎖
read committed是否
短期讀謂詞鎖
長期寫謂詞鎖
repeatable read是是
短期讀謂詞鎖
長期寫謂詞鎖
serilizable是是
長期讀謂詞鎖
長期寫謂詞鎖
read uncommitted:標準定義中,在該級別中不允許存在更新操作,也就是說在該級別的所有事務都是唯讀的,但是這種級別允許讀取別的事務已經更改但還沒有提交的資料,這樣就會導致髒讀。比如事務a更改了user的使用者名為usera,但是還未提交,但此種級別的事務b讀取了該資料,但是事務a又失敗了,導致回滾,這樣事務b其實讀到了無用的中間資料。
read committed:該級別會導致兩種錯誤讀取:
1.不可重複讀取:假設事務a已經讀取了某條資料,因為是短期讀鎖,導致事務a釋放對資料的鎖,此時事務b申請到了對事務a已經讀取事務的寫鎖,並更改資料並提交,當事務a再次讀取該資料時,資料已經改變。
2.更新丟失:比如事務a和事務b同時讀取了某條資料,初始值都是100,事務a的意圖是在100的基礎上加上40,得到結果140,事務b的意思是在這條資料上增加50,按照正常的模式,得到的最終值應該是190,但是由於資料事務a和b都讀到的是初始資料,事務a提交後,此時該資料應該是140,但是b已經讀取了舊資料100,然後b再更新,導致結果150,這樣就產生了錯誤的結果,序列如下:r1(a,100)r2(a,100)w1(a,140)c1 w2(a,150)c2,其中r1表示事務a的讀,w1表示事務a的寫,b也同樣。
repeatable read:在該隔離機制下,遮蔽了以上會出現的問題。但是該級別使用了短期的讀謂詞鎖,這樣會導致幻像讀取,比如事務a讀取了id>0的所有記錄。資料庫可能需要裝入整裝表逐個遍歷該張表的所有記錄,完成每一條記錄的讀取和where條件的比對,然後謂詞讀鎖釋放,但當此時,事務a未提交事務,此進事務b插入了一條資料滿足id>0,但是因為事務a已經釋放了id>0的謂詞鎖,會導致檢測不到事務b的提交資料。這種幻像讀在serilizable中可以去除,因為在seriliable中,使用了長期讀謂詞鎖,這樣事務b插入資料時,會導致鎖衝突,從而避免了幻像讀取。
hibernate資料庫連線
size 12 昨天學習hibernate一天,使用sqlserver2000資料庫,今天早上嘗試了一下mysql資料庫,發現大同小異,不過還是記在這裡吧,好記性不如個爛鍵盤 size color blue 使用mysql資料庫時候的hibernate.cfg.xml檔案內容 color color...
資料庫隔離級別
read uncommited 讀未提交 最低級別,可讀取未提交事物的資料,這會導致髒讀,比如 某時刻會話a修改了乙個資料,但還未提交,此時會話b,讀取了該資料,這是,會話a回滾了事物,這就導致資料出現了不一致狀態,這就是髒讀 read commited 提交讀 避免了髒讀,但會導致不可重複讀,例如...
資料庫隔離級別
資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀 不可重複讀 幻讀read uncommitted re...