MySQL的四種隔離級別


1. 定義

MySQL 中事務的隔離級別一共分為四種,分別如下:

  • 序列化(SERIALIZABLE):如果隔離級別為序列化,則用戶之間通過一個接一個順序地執行當前的事務,這種隔離級別提供了事務之間最大限度的隔離。
  • 可重復讀(REPEATABLE READ):在可重復讀在這一隔離級別上,事務不會被看成是一個序列。不過,當前正在執行事務的變化仍然不能被外部看到,也就是說,如果用戶在另外一個事務中執行同條 SELECT 語句數次,結果總是相同的。(因為正在執行的事務所產生的數據變化不能被外部看到)。
  • 提交讀(READ COMMITTED):READ COMMITTED 隔離級別的安全性比 REPEATABLE READ 隔離級別的安全性要差。處於 READ COMMITTED 級別的事務可以看到其他事務對數據的修改。也就是說,在事務處理期間,如果其他事務修改了相應的表,那么同一個事務的多個 SELECT 語句可能返回不同的結果。
  • 未提交讀(READ UNCOMMITTED):READ UNCOMMITTED 提供了事務之間最小限度的隔離。除了容易產生虛幻的讀操作和不能重復的讀操作外,處於這個隔離級的事務可以讀到其他事務還沒有提交的數據,如果這個事務使用其他事務不提交的變化作為計算的基礎,然后那些未提交的變化被它們的父事務撤銷,這就導致了大量的數據變化。

2. 實踐

2.1 查看隔離級別

通過如下 SQL 可以查看數據庫實例默認的全局隔離級別和當前 session 的隔離級別:

MySQL8 之前使用如下命令查看 MySQL 隔離級別:

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

查詢結果如圖:

 

 

 可以看到,默認的隔離級別為 REPEATABLE-READ,全局隔離級別和當前會話隔離級別皆是如此。

設置隔離級別:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

2.1 READ UNCOMMITTED

首先創建一個簡單的表,預設兩條數據,如下:

 

 臟讀

一個事務讀到另外一個事務還沒有提交的數據,稱之為臟讀。具體操作如下:

首先打開兩個SQL操作窗口,假設分別為 A 和 B,在 A 窗口中輸入如下幾條 SQL (輸入完成后不用執行):

START TRANSACTION;
UPDATE account set balance=balance+100 where name='javaboy';
UPDATE account set balance=balance-100 where name='itboyhub';
COMMIT;

在 B 窗口執行如下 SQL,修改默認的事務隔離級別為 READ UNCOMMITTED,如下:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

接下來在 B 窗口中輸入如下 SQL,輸入完成后,首先執行第一行開啟事務(注意只需要執行一行即可):

START TRANSACTION;
SELECT * from account;
COMMIT;

接下來執行 A 窗口中的前兩條 SQL,即開啟事務,給 javaboy 這個賬戶添加 100 元。

進入到 B 窗口,執行 B 窗口的第二條查詢 SQL(SELECT * from user;),結果如下:

 

 

可以看到,A 窗口中的事務,雖然還未提交,但是 B 窗口中已經可以查詢到數據的相關變化了。

這就是臟讀問題。

不可重復讀

不可重復讀是指一個事務先后讀取同一條記錄,但兩次讀取的數據不同,稱之為不可重復讀。具體操作步驟如下(操作之前先將兩個賬戶的錢都恢復為1000):

首先打開兩個查詢窗口 A 和 B ,並且將 B 的數據庫事務隔離級別設置為 READ UNCOMMITTED。具體 SQL 參考上文,這里不贅述。

在 B 窗口中輸入如下 SQL,然后只執行前兩條 SQL 開啟事務並查詢 javaboy 的賬戶:

START TRANSACTION;
SELECT * from account where name='javaboy';
COMMIT;

前兩條 SQL 執行結果如下:

 

 在 A 窗口中執行如下 SQL,給 javaboy 這個賬戶添加 100 塊錢,如下:

START TRANSACTION;
UPDATE account set balance=balance+100 where name='javaboy';
COMMIT;

再次回到 B 窗口,執行 B 窗口的第二條 SQL 查看 javaboy 的賬戶,結果如下

javaboy 的賬戶已經發生了變化,即前后兩次查看 javaboy 賬戶,結果不一致,這就是不可重復讀

和臟讀的區別在於,臟讀是看到了其他事務未提交的數據,而不可重復讀是看到了其他事務已經提交的數據(由於當前 SQL 也是在事務中,因此有可能並不想看到其他事務已經提交的數據)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM