★ 臟讀 : 讀取了前一事務 未提交 的數據 ;
不可重復讀 : 讀取了前一事務 提交 的數據;
★ 幻讀 與 不可重復讀
common :都是讀取了另一條已經提交的事務(這點與臟讀不同);
differences :
不可重復讀 :查詢的都是同一個數據項
幻讀 :針對的是一批數據整體(比如數據的個數)
不可重復讀eg: <當隔離級別設置為Repeatable read 時,可以避免不可重復讀>
eg2: 在事務A中,讀取到張三的工資為5000,操作沒有完成,事務還沒提交。
與此同時,事務B把張三的工資改為8000,並提交了事務。
隨后,在事務A中,再次讀取張三的工資,此時工資變為8000。在一個事務中前后兩次讀取的結果並不致,導致了不可重復讀。(大部分數據庫缺省的事物隔離級別都不會出現這種狀況)
幻讀eg:
eg1: 目前工資為5000的員工有10人,事務A讀取所有工資為5000的人數為10人。
此時,事務B插入一條工資也為5000的記錄,並且commit了。
這時,事務A再次讀取工資為5000的員工,記錄為11人。此時產生了幻讀。
(大部分數據庫缺省的事物隔離級別都會出現這種狀況,此種事物隔離級別將帶來表級鎖)
eg2: A將db中all學生的score從數字分數改變為ABCDE等級,但是B就在此時插入了一條具體的分數,當A改完后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣.這就叫幻讀.
一下部分原文:https://blog.csdn.net/nanxiaotao/article/details/80412196
1.事務的特性(ACID)
(1)原子性(Atomicity)。事務中所涉及的程序對數據庫的修改操作要么全部成功,要么全部失敗。
(2)一致性(Consistency)。事務執行前和執行后來源和去向保持平衡。
(3)隔離性(Isolation)。並發時每個事務是隔離的,相互不影響。
(4)持久性(Durubility)。一旦事務成功提交,應該保證數據的完整存在。
2.事務隔離級別
(1)read uncommitted 未提交讀 所有事務都可以看到沒有提交事務的數據。
eg: 公司發工資了,領導把5000元打到A的賬號(正常工資2千)上,但是該事務並未提交,而A正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。
但是領導隨后發現給A的工資發多了,於是迅速回滾了事務,修改金額后,將事務提交,最后A實際的工資只有2000元,A空歡喜一場。
剖析:臟讀:“事務A:leader給A發工資”,
“事務B:A查詢工資賬戶”,事務B讀取了事務A尚 uncommitted 的數據。當隔離級別設置為Read uncommitted時,就可能出現臟讀,如何避免臟讀,請看下一個隔離級別。
(2)read committed 提交讀 事務成功提交后才可以被查詢到。
eg: A拿着工資卡去消費,出門前查到卡里是2000元,湊巧緊接着她的老婆作為急用把A工資卡的2000元轉到另一賬戶, 當A准備付款時,卻發現工資卡已經沒有錢,扣款失敗......
剖析:兩個並發的事務,“事務A:A消費”,
“事務B:A的老婆網上轉賬”,事務A事先讀取了數據,緊接着事務B更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
當隔離級別設置為Read committed時,避免了臟讀,但是可能會造成不可重復讀。
大多數數據庫的默認級別就是Read committed,比如Sql Server , Oracle。如何解決不可重復讀這一問題,請看下一個隔離級別。
(3)repeatable 重復讀 同一個事務內多次查詢卻返回了不同的數據值,即 可能將未提交的記錄查詢出來,而出現幻讀。注:Mysql的默認隔離級別就是Repeatable read。
前言:當隔離級別設置為Repeatable read 時,可以避免不可重復讀。當A拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),A的老婆就不可能對該記錄進行修改,也就是A的老婆不能在此時轉賬。
雖然Repeatable read避免了不可重復讀,但還有可能出現幻讀 。
eg1: A的老婆在銀行工作,她可以很方便的查看A的信用卡消費記錄。月末了,她正在查詢A當月的消費情況 (select sum(amount) from transaction where month = ‘本月’)為80元,而A此時正好在某收銀台買單,
消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨后A的老婆將A當月信用卡消費的明細打印到A4紙上,卻發現消費總額為1080元,A的老婆很詫異,以為出 現了幻覺,幻讀就這樣產生了。
eg2: 在事務A中,讀取到張三的工資為5000,操作沒有完成,事務還沒提交。
與此同時,事務B把張三的工資改為8000,並提交了事務。
隨后,在事務A中,再次讀取張三的工資,此時工資變為8000。在一個事務中前后兩次讀取的結果並不致,導致了不可重復讀。(大部分數據庫缺省的事物隔離級別都不會出現這種狀況)
(4)Serializable可串行化 強制的進行排序,在每個讀讀數據行上添加共享鎖。會導致大量超時現象和鎖競爭。這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。除了防止臟讀,不可重復讀外,還避免了幻讀。
MySQL:
mysql默認的事務處理級別是'REPEATABLE-READ',也就是可重復讀
1.查看當前會話隔離級別
select @@tx_isolation;
2.查看系統當前隔離級別
select @@global.tx_isolation;
3.設置當前會話隔離級別
set session transaction isolatin level repeatable read;
4.設置系統當前隔離級別
set global transaction isolation level repeatable read;
Oracle:
oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。
默認系統事務隔離級別是READ COMMITTED,也就是讀已提交
1.查看系統默認事務隔離級別,也是當前會話隔離級別
--首先創建一個事務
declare
trans_id Varchar2(100);
begin
trans_id := dbms_transaction.local_transaction_id( TRUE );
end;
--查看事務隔離級別
SELECT s.sid, s.serial#,
CASE BITAND(t.flag, POWER(2, 28))
WHEN 0 THEN 'READ COMMITTED'
ELSE 'SERIALIZABLE'
END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');