幻讀和不可重復讀的區別


 
 

MySQl

MySql默認的隔離級別為Repeatable Read,因此只會出現幻讀的情況。
 

幻讀

事務在插入已經檢查過不存在的記錄時,驚奇的發現這些數據已經存在了,之前的檢測獲取到的數據如同鬼影一般。

例子:

在事務1中,查詢User表id為1的是用戶否存在,如果不存在則插入一條id為1的數據。

 

[java]  view plain  copy
 
  1. select * from User where id = 1;  
在事務1查詢結束后,事務2往User表中插入了一條id為1的數據。

 

 

[java]  view plain  copy
 
  1. insert into `User`(`id`, `name`) values (1, 'Joonwhee');  
此時,由於事務1查詢到id為1的用戶不存在,因此插入1條id為1的數據。

 

 

[java]  view plain  copy
 
  1. insert into ` User`(`id`, `name`) values (1, 'Chillax');  
但是由於事務2已經插入了1條id為1的數據,因此此時會報主鍵沖突,對於事務1 的業務來說是執行失敗的,這里事務1 就是發生了幻讀,因為事務1讀取的數據狀態並不能支持他的下一步的業務,見鬼了一樣。這里要靈活的理解讀取的意思,第一次select是讀取,第二次的insert其實也屬於隱式的讀取,只不過是在mysql的機制中讀取的,插入數據也是要先讀取一下有沒有主鍵沖突才能決定是否執行插入。

 

Oracle

Oracle默認的隔離級別為Read Committed,因此可能出現不可重復度和幻讀。
 

不可重復讀

同樣的條件,你讀取過的數據,再次讀取出來發現值不一樣了。

例子:

在事務1中,JoonWhee讀取了自己的工資為1000,但是此時事務1的操作還並沒有完成 ,后面還有1次相同的讀取操作。

 

[java]  view plain  copy
 
  1. con1 = getConnection();    
  2. select salary from employee where employeeName ="JoonWhee";  

 

在事務2中,這時財務人員修改了JoonWhee的工資為2000,並提交了事務。

 

[java]  view plain  copy
 
  1. con2 = getConnection();    
  2. update employee set salary = 2000 where employeeName = "JoonWhee";    
  3. con2.commit();  

 

在事務1中,JoonWhee再次讀取自己的工資時,工資變為了2000 。

 

[java]  view plain  copy
 
  1. //con1  
  2. select salary from employee where employeeName ="JoonWhee";   

 

在一個事務中前后兩次讀取的結果並不致,導致了不可重復讀。

 

幻讀

同樣的條件,第1次和第2次讀出來的記錄數不一樣。

例子:

目前工資為1000的員工有10人。 

事務1,讀取所有工資為1000的員工,共讀取10條記錄 。

 

[java]  view plain  copy
 
  1. con1 = getConnection();    
  2. Select * from employee where salary =1000;  

 

這時另一個事務向employee表插入了一條員工記錄,工資也為1000 

 

[java]  view plain  copy
 
  1. con2 = getConnection();    
  2. Insert into employee(employeeName,salary) values("Lili",1000);    
  3. con2.commit();   

 

事務1再次讀取所有工資為1000的員工,共讀取到了11條記錄,這就產生了幻讀。 

 

[java]  view plain  copy
 
  1. //con1    
  2. select * from employee where salary =1000;  

 

 
作者:小朋友
鏈接:https://www.zhihu.com/question/47007926/answer/253406510
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

臟讀:(同時操作都沒提交的讀取)

臟讀又稱無效數據讀出。一個事務讀取另外一個事務還沒有提交的數據叫臟讀。

例如:事務T1修改了一行數據,但是還沒有提交,這時候事務T2讀取了被事務T1修改后的數據,之后事務T1因為某種原因Rollback了,那么事務T2讀取的數據就是臟的。

解決辦法:把數據庫的事務隔離級別調整到READ_COMMITTED

不可重復讀:(同時操作,事務一分別讀取事務二操作時和提交后的數據,讀取的記錄內容不一致)

不可重復讀是指在同一個事務內,兩個相同的查詢返回了不同的結果。

例如:事務T1讀取某一數據,事務T2讀取並修改了該數據,T1為了對讀取值進行檢驗而再次讀取該數據,便得到了不同的結果。 解決辦法:把數據庫的事務隔離級別調整到REPEATABLE_READ

幻讀:(和可重復讀類似,但是事務二的數據操作僅僅是插入和刪除,不是修改數據,讀取的記錄數量前后不一致)

例如:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入(注意時插入或者刪除,不是修改))了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣。這就叫幻讀。

解決辦法:把數據庫的事務隔離級別調整到SERIALIZABLE_READ


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM