案例:
操作步驟及解讀:
1 1. 建立資料庫: 2 create database ceshi; 3 4 2.建立表: 5 6 CREATE TABLE test_table ( 7 id INT PRIMARY KEY, 8 value VARCHAR(100) 9 ); 10 插入資料 11 INSERT INTO test_table (id, value) VALUES (1, 'yujian'); 12 13 3.檢視當前隔離級別 14 當前會話: SELECT @@session.transaction_isolation; 15 全域性: SELECT @@global.transaction_isolation; 16 17 4.設定會話就是在當前頁面生效,其它頁面不生效。我們需要建立兩個會話頁面。(都是可重複讀級別。) 18 19 5.配置讀取未提交級別,兩個會話都設:SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 20 21 髒讀: 22 23 髒讀指的是讀當前事務讀到了其他事務未提交的資料,未提交意味著這些資料可能會回滾,也就是可能最終不會存到資料庫中,也就是不存在的資料。讀到了並一定最終存在的資料。 24 6.首先我們在第一張會話裡面建立事務並修改資料: 25 開啟事務:START TRANSACTION; 26 修改資料:UPDATE test_table SET value = 'llnb' WHERE id = 1; 27 28 7.然後我們在第二張會話裡可以查到第一張剛剛修改的資料,但是第一張會話的事務並沒有提交 29 30 31 不可重複讀: 32 不可重複讀指的是在一個事務內,最開始讀到的資料和事務結束前的任意時刻讀到的同一批資料出現不一致的情況 33 34 8.我們先回滾一下,回到最初的狀態:ROLLBACK; 35 9.在兩張會話裡面都建立事務:START TRANSACTION; 36 37 10.在第一張會話裡查一下,會發現id為1的欄位裡是yujian 38 11.然後在第二張會話裡修改欄位並提交事務: 39 40 UPDATE test_table SET value = 'llnb' WHERE id = 1; 41 COMMIT; 42 12.對比第一張會話前後兩次查詢到的資料,會發現兩次查詢的資料是不一樣的。 43 44 45 幻讀: 46 47 幻讀就是select 某記錄是否存在,不存在,準備插入此記錄,但執行 insert 時發現此記錄已存在,無法插入 48 49 13.先回滾一下:ROLLBACK; 50 14.在一二張會話裡開啟事務:START TRANSACTION; 51 15.在第一張會話裡查詢所有記錄 52 SELECT * FROM test_table; 53 16.然後在第二張會話裡新增第二條記錄並提交 54 55 INSERT INTO test_table (id, value) VALUES (2, 'llnb'); 56 COMMIT; 57 58 17.在第一張會話裡查詢所有,會發現原本只有一條記錄的表多了一條記錄
補充:
在 MySQL 中事務的隔離級別有以下 4 種:
- 讀未提交(READ UNCOMMITTED)
- 讀已提交(READ COMMITTED)
- 可重複讀(REPEATABLE READ)
- 序列化(SERIALIZABLE)
MySQL 預設的事務隔離級別是可重複讀(REPEATABLE READ),這 4 種隔離級別的說明如下。
1.READ UNCOMMITTED
讀未提交,也叫未提交讀,該隔離級別的事務可以看到其他事務中未提交的資料。該隔離級別因為可以讀取到其他事務中未提交的資料,而未提交的資料可能會發生回滾,因此我們把該級別讀取到的資料稱之為髒資料,把這個問題稱之為髒讀。
2.READ COMMITTED
讀已提交,也叫提交讀,該隔離級別的事務能讀取到已經提交事務的資料,因此它不會有髒讀問題。但由於在事務的執行中可以讀取到其他事務提交的結果,所以在不同時間的相同 SQL 查詢中,可能會得到不同的結果,這種現象叫做不可重複讀。
3.REPEATABLE READ
可重複讀,是 MySQL 的預設事務隔離級別,它能確保同一事務多次查詢的結果一致。但也會有新的問題,比如此級別的事務正在執行時,另一個事務成功的插入了某條資料,但因為它每次查詢的結果都是一樣的,所以會導致查詢不到這條資料,自己重複插入時又失敗(因為唯一約束的原因)。明明在事務中查詢不到這條資訊,但自己就是插入不進去,這就叫幻讀 (Phantom Read)。
4.SERIALIZABLE
序列化,事務最高隔離級別,它會強制事務排序,使之不會發生衝突,從而解決了髒讀、不可重複讀和幻讀問題,但因為執行效率低,所以真正使用的場景並不多。
補充2:
1.事務相關的常用命令
# 檢視 MySQL 版本
select version();
# 開啟事務
start transaction;
# 提交事務
commit;
# 回滾事務
rollback;