1. 程式人生 > >★ MYSQL隔離級別 通俗理解 + mysql、oracle默認事務隔離級別

★ MYSQL隔離級別 通俗理解 + mysql、oracle默認事務隔離級別

缺省 ... city blog 一場 避免 持久性 user from

★  臟讀    : 讀取了前一事務 未提交 的數據 ;

  不可重復讀 : 讀取了前一事務 提交 的數據;

★ 幻讀 與 不可重復讀    

  common  :都是讀取了另一條已經提交的事務(這點與臟讀不同);

  differences :

    不可重復讀 :查詢的都是同一個數據項

    幻讀    :針對的是一批數據整體(比如數據的個數)

不可重復讀eg:   <當隔離級別設置為Repeatable read 時,可以避免不可重復讀>

  eg2: 在事務A中,讀取到張三的工資為5000,操作沒有完成,事務還沒提交。

    與此同時,事務B把張三的工資改為8000,並提交了事務。

    隨後,在事務A中,再次讀取張三的工資,此時工資變為8000。在一個事務中前後兩次讀取的結果並不致,導致了不可重復讀。(大部分數據庫缺省的事物隔離級別都不會出現這種狀況)

幻讀eg:

  eg: 目前工資為5000的員工有10人,事務A讀取所有工資為5000的人數為10人。

    此時,事務B插入一條工資也為5000的記錄,並且commit了。

    這時,事務A再次讀取工資為5000的員工,記錄為11人。此時產生了幻讀。

    (大部分數據庫缺省的事物隔離級別都會出現這種狀況,此種事物隔離級別將帶來表級鎖)

一下部分原文: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‘);

★ MYSQL隔離級別 通俗理解 + mysql、oracle默認事務隔離級別