1. 程式人生 > >sql有關髒讀,虛讀,幻讀及防範

sql有關髒讀,虛讀,幻讀及防範

事務的特性:

  • 原子性:指處於同一個事務中的多條語句是不可分割的。
  • 一致性:事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。比如轉賬,轉賬前兩個賬戶餘額之和為2k,轉賬之後也應該是2K。
  • 隔離性:指多執行緒環境下,一個執行緒中的事務不能被其他執行緒中的事務打擾
  • 永續性:事務一旦提交,就應該被永久儲存起來。

事務隔離性問題: 
如果不考慮事務的隔離性,會出現以下問題:

  • 髒讀:指一個執行緒中的事務讀取到了另外一個執行緒中未提交的資料。
  • 不可重複讀(虛讀):指一個執行緒中的事務讀取到了另外一個執行緒中提交的update的資料。
  • 幻讀:指一個執行緒中的事務讀取到了另外一個執行緒中提交的insert的資料。

隔離級別:

隔離級別 髒讀(Dirty Read) 不可重複讀(NonRepeatable Read) 幻讀(Phantom Read)
未提交讀(Read uncommitted) 可能 可能 可能
已提交讀(Read committed) 不可能 可能 可能
可重複讀(Repeatable read) 不可能 不可能 可能
可序列化(Serializable ) 不可能 不可能 不可能

級別越高,資料越安全,但效能越低。

A 髒讀

髒讀就是指讀到還沒完全弄好的資料。比如,你要讀取資料庫中的欄位A、欄位B,你讀取時恰巧有其他使用者正在更新這2個欄位,而且是先更新A、再更新B,此時就可能會發生髒讀:
1、如果都未更新你就讀取了,或者都更新完了你才讀取,這都不是髒讀,因為你得到的是更新前的有效值,或完全更新後的值。
2、如果那個使用者更新一半你就讀取了,也就是說更新了A,正打算要更新B但尚未更新時,你就讀取了,此時你得到的就是髒資料

 
B 不可重複讀
不可重複讀:所謂的虛讀,也就是大家經常說的不可重複讀,是指在資料庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一資料,事務T2讀取並修改了該資料,T1為了對讀取值進行檢驗而再次讀取該資料,便得到了不同的結果。 
一種更易理解的說法是:在一個事務內,多次讀同一個資料。在這個事務還沒有結束時,另 一個事務也訪問該同一資料。那麼,在第一個事務的兩次讀資料之間。由於第二個事務的修改,那麼第一個事務讀到的資料可能不一樣,這樣就發生了在一個事務內 兩次讀到的資料是不一樣的,因此稱為不可重複讀,即原始讀取不可重複。

C 幻讀

      幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,比如這種修改涉及到表中的“全部資料行”。同時,第二個事務也 修改這個表中的資料,這種修改是向表中插入“一行新資料”。那麼,以後就會發生操作第一個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一 樣.一般解決幻讀的方法是增加範圍鎖RangeS,鎖定檢鎖範圍為只讀,這樣就避免了幻讀。簡單來說,幻讀是由插入或者刪除引起的。 

大致的區別在於不可重複讀是由於另一個事務對資料的更改所造成的,而幻讀是由於另一個事務插入或刪除引起的。

不可重複讀(虛讀)和幻讀的差別: 
從總的結果來看, 似乎兩者都表現為兩次讀取的結果不一致. 
但如果你從控制的角度來看, 兩者的區別就比較大: 
對於前者, 只需要鎖住滿足條件的記錄 

對於後者, 要鎖住滿足條件及其相近的記錄  

如何防範??


1 避免髒讀: 更新的時候加鎖 ,避免select ,更新完了猜讓查詢,避免select兩個欄位的時候,一個欄位更新了,一個欄位沒有更新
2 避免虛讀: 查詢的時候加鎖,避免update ,從而避免兩次查詢結果不一致
3 避免幻讀: 譬如在一定條件下update,那對這個一定條件加鎖,避免update過程中insert