數據庫庫事務隔離級別是個什麼玩意


一直很想對數據庫事務作一點總結,今天終於靜下心來小小的總結一下。 sql

1、數據庫事務的特徵 數據庫

一、原子性 瀏覽器

原子,顧名思義,天然界中的最小粒子(儘管物理上原子還可分割成夸克的什麼玩意,這個咱們就無論了)。定義一組操做集合,若是隻執行一個子集,這就破壞的事務的目標,事務必須不可分割,要麼所有執行,要麼所有不執行。 安全

        二、一致性 session

在事務完成時,全部數據必須保持一致的狀態。例如:張三給李四轉帳100,元,張三帳號扣除了100,而李四帳號卻沒有變化,這就違背了一致性。 多線程

三、隔離性 併發

多用戶操做同一條數據時,必須時相互隔離,以避免A用戶操做影響了B用戶.。 分佈式

        四、持久性 高併發

一個事務成功了,那麼就一定持久化到磁盤了,就算斷電了,下次重啓,數據依然正確無缺。 性能

2、幾個有趣的現象

不少時候,咱們習慣這樣描述咱們的系統,高併發、分佈式、集羣等等,對於一個多用戶、多線程的應用,不可避免的共同訪問相同的資源,若是沒有一套規則去約束這些操做,勢必要出亂子,這就是咱們要重點討論的事務隔離。

咱們先來看看幾個有趣現象:

一、髒讀

期末考過了半個月,小明正在急切的查分,一遍一遍的刷新着瀏覽器,數學分數怎麼還沒出來??碰巧數學老師在錄入分數,恰好錄到小明90分,提交請求,剛好小明刷新,90分,欣喜若狂。而此時數學老師發現錄入錯誤,撤銷了事務,小明再次查詢,分數消失,小明此時是各類猜想。

這個過程當中,有兩個事務在操做同一條數據:以下表,T表明時間

事務1

事務2

T1開啓事務

 

 

T2開啓事務

 

T3數學老師開始錄入分數90

T4小明查到分數90

 

 

T5老師發現錄入錯誤回滾數據

T6小明憂傷的查不到分數了

 

T7提交事務

  

很明顯,事務1讀到了事務2未提交的數據。

二、不可重複讀

最終小明查到了分數爲59,傷心的要準備補考了,準備把成績打印出來,發現打印出來的成績是69,原來老師發現有道題目解題思路新穎,要額外給小明加10分。

事務1

事務2

T1事務開啓

 

T2小明查到分數59

 

 

T3事務開啓

 

T4修改分數爲69

 

T5提交事務

T6小明打印成績69

 

T7提交事務


三、幻讀

小明一直在焦急的等待最後一門英語成績,發現始終沒有出來,便想把已經出來的成績先打印,最後發現打印出來的有英語成績。

事務1

事務2

       T1事務開啓

 

T2小明查分,不包括英語

 

 

T3開啓事務

 

T4英語老師錄入分數

 

T5提交事務

T6小明打印到了英語成績

 

T7提交事務

 

注:有人要問了,不可重複讀和幻讀,一個德行,有什麼區別,不可重複讀是讀到了修改數據,幻讀是讀到了新增的數據,有又有什麼不一樣呢,數據庫的鎖不同,下次分享。

3、事務的隔離級別

以上的現象,不一樣的事務隔離級別,會產生對於的現象。

事務隔離級別:

一、讀未提交(READ-UNCOMMITTED);

二、讀已提交(READ-COMMITTED);

三、可重複讀(REPEATABLE-READ);

四、序列化(SERIABLIABLE)

隔離級別

髒讀

不可重複讀

幻讀

READ-UNCOMMITTED

Y

Y

Y

READ-COMMITTED

N

Y

Y

REPEATABLE-READ

N

N

Y

SERIALIZABLE

N

N

N

4、MySql的隔離級別和對應現象

Mysql默認的隔離級別是REPEATABLE-READ

一、髒讀

(1)、設定數據庫隔離級別爲READ-UNCOMMITTED

(2)、A事務開啓,查詢,沒查到數據;

(3)、B事務開啓,修改分數,但不提交;

(4)、A事務查詢,小明查到了分數90

(5)、B事務回滾

(6)、A事務再次查詢,已經查不到;

(7)、A事務提交;

下面咱們看把隔離級別設置成READ-COMMITTED可否解決這個問題。

(1)、設定隔離級別爲READ-COMMITTED;;

(2)、A事務查詢

(3)、B事務修改,但不提交;

(4)、A事務再次查詢,卻查詢不到;

(5)、B事務提交;

(6)、A事務再次查詢,查詢到了分數;

二、不可重複讀

緊接着上面的例子,上面的A事務還沒結束。

(1)、B事務再次修改分數提交;

(2)、A事務再次查詢;

那麼這個時候有同窗要問了,若是B事務沒有提交,有C事務來修改小明的分數會怎麼樣??下面咱們就來看看:

很明顯,C事務沒法修改這條記錄,這條記錄已經被加鎖。咱們略過這個小插曲。

兩次讀取的數據不同,這就是不可重複讀。讀到的是其餘事務已提交的數據,這也是無可厚非,固然有些系統特別變態要求可重複讀。

下面咱們看看REPEATABLE-READ,可否解決咱們的問題:

(1)、設定事務隔離級別爲REPEATABLE-READ

(2)、A事務開啓,讀數據;

(3)、B事務開啓,修改數據,並提交;

(4)、A事務再次查詢,發現結果沒變;

很明顯,在REPEATABLE-READ級別下,A事務讀取數據是徹底不受其餘事務影響的,這就解決了不可重複讀的問題。

三、幻讀

緊接着上面的例子,事務A再次查詢,碰巧再次以前B事務新增了一條記錄,英語成績被錄入進來。

(1)、B事務新增一條記錄,並提交;

(2)、A事務再次查詢;

這裏有同窗就要奇怪了,爲何沒有查到英語成績,理論上要出現幻讀了,這是Why??

Mysql的可重複讀的實現和其餘數據庫是有區別的,不會形成幻讀,那麼仍是要說說幻讀,幻讀,就是同一個事務內,屢次查詢,讀取到其餘session 事務insert並已經提交的數據。

那麼咱們來看看最後一個隔離級別SERIALIZABLE

(1)、設置隔離級別爲SERIALIZABLE

(2)、B事務開啓,新增記錄,並不提交;

(3)、A事務開啓事務查詢;

B事務沒提交,A事務就阻塞,就連select也會阻塞,這就是串行化得名的緣由,只能順序執行,全部安全級別最高,性能最低。

至於JDBC與隔離級別,請聽下回分解。

相關文章
相關標籤/搜索