MySQL四種隔離級別

什麼是事務

事務是應用程序中一系列嚴密的操做,全部的操做必須成功完成,不然每一個操做中國所作的全部更改都會被撤銷。也就是事務具備原子性,一個事務中的一系列的操做要麼所有成功,要麼一個都不作。mysql

事務的結束有兩種,當事務中的全部步驟所有成功執行時,事務提交。若是一個步驟失敗,將發生回滾操做,撤銷以前到事務開始時的全部操做。sql

事務的ACID

事務具備四個特徵:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持續性(Durability)。這一個特性簡稱爲ACID特性。數據庫

  1. 原子性:事務是數據庫的邏輯工做單位,事務中包含的各操做要麼都作、要麼都不作。
  2. 一致性:事務執行的結果必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。所以當數據庫只包含成功事務提交的結果是,就說數據庫處於一致性狀態。若是數據庫系統運行中發生故障,有些事務還沒有完成就被迫中斷,這些未完成事務對數據庫所作的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是不一致的狀態。
  3. 隔離性:一個事務的執行不被其餘事務干擾。即一個事務內部的操做及使用的數據對其餘併發事務是隔離的,併發執行的各個事務之間不能互相干擾。
  4. 持續性:也稱永久性,指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其餘操做或者故障不該該對其執行結果有任何影響。

事務操做:session

  • 讀鎖(共享)併發

  • 寫鎖(獨佔)性能

Mysql的四種隔離級別

SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級通常支持更高的併發處理,並擁有更低的系統開銷。測試

  1. Read Uncommitted(讀取未提交內容)3d

    在該隔離級別,全部事物均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用。所以它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)code

  2. Read Committed(讀取提交內容)blog

    這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別也支持所謂的不可重讀(NonRepeatable Read),由於同一個事務的其餘實例在該實例處理期間可能會有新的commit,因此統一Select可能返回不一樣的結果。

  3. Repeatable Read(可重讀)

    這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到相同的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發生有新的「幻影」行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

  4. Serializable(可串行化)

    這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,他是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。

這四種隔離級別採用不一樣的鎖類型來實現,若讀取的是同一份數據的話,就容易發生問題。

  1. 髒讀(Dirty Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,後一個書屋所讀取的數據會是不正確的。(大白話說:讀未提交。一個事務讀取了另外一個事務改寫還未提交的數據,若是另外一個事務在稍後時刻回滾則髒讀發生了。)
  2. 不可重複讀(Non-Repeatable Read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中插入了一個事務,更新了原有的數據。(大白話說:讀不回去。一個事務在進行相同條件的查詢連續的兩次或者兩次以上,每次結果都不一樣,查詢期間,有其餘事務進行update操做)
  3. 幻讀(Phantom Read):在一個事務的兩次查詢中數據行數不一致。例若有一個事務查詢了幾行數據,而另外一個事務卻在此時插入了新的幾行數據,先前的事務在接下來的查詢中,就有幾列數據是未查詢出來的,若是此時插入和另外一個事務插入的數據,就會發生報錯。(大白話說:讀多了。一個事務進行相同條件查詢。在後來的查詢中會發現原來沒有的記錄,在查詢期間,有其餘事務進行insert操做)

在MySQL中,實現了這四種隔離級別,分別有可能產生問題以下所示:

隔離級別 髒讀 不可重複讀 幻讀
Read Uncommited
Read Comitted
Repeatable Read
Serializable

測試MySQL的隔離級別

準備工做:

數據庫測試表信息
        
    create table `customers`(
    `id` int(11) unsigned not null AUTO_INCREMENT,
    `name` varchar(32) not null default '0',
    primary key(`id`)
)Engine=InnoDB AUTO_INCREMENT = 4 default charset=utf8;
insert into test(num) values(`tom`);
insert into test(num) values(`jerry`);
insert into test(num) values(`anny`);

髒讀

[A]

​ 2.關閉自動提交

set autocommit = 0;

3.開啓事務

start transaction;

​ 4.執行更新

update name set name ='jerry' where id =1;

[B]

​ 1.設置b的隔離級別

set session transaction isolation level read uncommitted;

​ 5.查詢客戶

select * from customers

具體操做:

  1. [B機器]:設置隔離級別爲read uncommitted

image-20190818210542946

  1. [A機器]:開啓事務,執行更新

    image-20190818210842464

  2. [B機器]:查詢全部數據

    image-20190818210927145

  3. [A機器]:回滾事務

    image-20190818210947974

  4. [B機器]:髒讀致使了數據不一致

    image-20190818211005282

解決:

6.[B機器]:隔離級別提高爲read committed;

set session transaction isolation level read committed

image-20190818211319403

7.[A機器]:從新開啓事務,更新數據

image-20190818211407836

8.[B機器]:查詢數據

image-20190818211433444

不可重複讀

[A]

  1. 設置隔離級別 read committed

    set session transaction isolation level read committed;

  2. 關閉自動提交

    set autocommit = 0;

  3. 開啓事務

    start transaction;

  4. 查詢

    select name from customers where id =1;

[B]

5.開啓事務,更新數據,提交數據(默認是自動提交)

update customers set names = 'jerry' where id =1

具體操做:

​ [A機器]:設置隔離級別,關閉自動提交,開啓事務,查詢數據

image-20190818214025228

[B機器]:更新數據

image-20190818214131433

[A機器]:再次查詢數據,發現數據已經被更新

image-20190818214207025

解決:提高隔離級別到repeatbale read

[A機器]:設置隔離級別,關閉自動提交,開啓事務,查詢數據

image-20190818214320652

若是遇到ERROR 1568,請commit以後再進行設置操做。

image-20190818214338120

[B機器]:更新數據

image-20190818214439252

[A機器]:查詢數據,發現數據沒有發生變化

image-20190818214527188

相關文章
相關標籤/搜索