天天看點

MySQL 事務隔離級别

MySQL 事務隔離級别

基本概念

  事務的基本特性

原子性(Atomicity): 當開啟事務後,後面的所有操作,要麼全部成功,要麼全部失敗。

一緻性(Consistency): 事務執行前後資料庫狀态保持一緻。

隔離性(Isolation): 在事務未送出前,它的操作對其他使用者是不可見的。

持久性(Durability): 一旦事務成功,将進行永久的變更,記錄與redo日志;

  事務并發引發的問題

髒讀:所讀取的資料已經被修改了,屬于沒有意義的資料。

不可重複讀:事務A多次讀取同一條資料,事務B在A讀取的過程中對這條資料進行了更改,導緻事務A讀取的資料中出現的結果不一緻。

幻讀:同樣一個查詢錯做在整個事務過程中多次執行後,查詢所得的結果集不一樣。(側重于新增和删除操作)

  事務的隔離級别

讀未送出(read-uncommitted):讀取其它事務未完成的結果。

不可重複讀(read-committed) :事務完成後,才能讀取該事務的資料更新後的結果。

可重複讀(repeatable-read) :在整個事務的過程中,對同一筆資料的讀取結果是相同的,不管其他事務是否同時在對同一筆資料進行更新,也不管其他事務對同一筆資料的更新送出與否。

串行化(serializable) :事務操作都必須依次順序執行,可以避免其他隔離級别遇到的所有問題,是最為安全的隔離級别, 但同時也是性能最差的隔離級别。

   不同隔離級别引發的問題

隔離級别 髒讀 不可重複讀 幻讀

讀未送出 Yes Yes Yes

不可重複讀 No Yes Yes

可重複讀 No No Yes

串行化 No No No

案例說明

   本此案例使用單表進行測試,具體表結構如下所示:

複制代碼

1 DROP TABLE IF EXISTS

user

;

2 CREATE TABLE

user

(

3

id

int(11) NOT NULL AUTO_INCREMENT,

4

name

varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,

5

age

int(11) NULL DEFAULT NULL,

6

balance

int(255) NULL DEFAULT NULL,

7 PRIMARY KEY (

id

) USING BTREE

8 )

9

10 INSERT INTO

user

VALUES (1, '張三', 21, 100);

11 INSERT INTO

user

VALUES (2, '李四', 21, 0);

  表中有兩條資料張三的餘額為100,李四的餘額為0;

  讀未送出

   在Windows環境下使用dos視窗(此處需要兩個視窗進行測試分别為A/B)進入mysql的用戶端,并切換到此表對應的資料庫下。

   在A視窗和B視窗下對其事務的模式進行設定并開啟事務。

1 SET session transaction isolation level read uncommitted;

2

3 START TRANSACTION;

  在視窗A中對張三的餘額進行調整(加50),在不進行送出的前提下在視窗B對張三的餘額進行查詢,結果如下:

  視窗A

  視窗B

  我們發現用戶端B的資料也是被更新了,但是,如果有一天由于某些問題,用戶端的這次更新進行了復原操作,那麼用戶端B中查詢的資料就屬于髒資料了,這時候就會有髒讀的問題。

不可重複讀

  同樣的打開兩個視窗并對其事務進行設定。

1 SET session transaction isolation level read committed;

  對在視窗A中對張三的餘額進行調整(加50),在不進行送出的前提下在視窗B對張三的餘額進行查詢,結果如下:

  這裡我們發現在A視窗沒有送出事務前B視窗無法拿到A視窗更新的資料,是以解決了髒讀的情況。

  下來我們對A視窗的資料進行送出。并再次查詢結果。

  

  這個時候B視窗的資料在A視窗送出事務前後的資料是不一緻的,是以會有不可重複讀的問題産生。

可重複讀

1 SET session transaction isolation level repeatable read;

對在視窗A中對張三的餘額進行調整(加50),在不進行送出的前提下在視窗B對張三的餘額進行查詢,結果如下:

  此時發現已經解決了不可重複讀的問題。

  這時候如果在視窗B對張三的資料再進行增加(+50)呢?那麼最終的資料會是多少呢?

  可見B視窗的資料是在A視窗的基礎上進行操作的,是以資料的一緻性沒有被破壞,因為可重複讀的隔離級别下使用了MVCC機制。

  下來我們在B視窗新增一條資料,并進行送出。

1 INSERT INTO

user

VALUES (3, '王五', 21, 200);

  用戶端A兩次結果發生了不一緻,出現幻讀。

串行化

1 SET session transaction isolation level serializable;

  視窗A對user表中的資料進行查詢,在視窗B對資料進行更新。

原文位址

https://www.cnblogs.com/brother-four/p/10711398.html