【MySQL資料庫】innodb事務的隔離級別
文章目錄
事務隔離級別分類
1.髒讀(一個事務,讀到另外一條未提交事務的資料) read uncommitted出現
- 如何避免:設定隔離級別為read committed或者更高
2.不可重複讀(一個事務多次讀取到的資料不一致) read committed出現
- 如何避免:設定隔離級別為repeatable read或者更高
3.幻讀(事務AB,事務A插入一條資料,事務B修改所有的資料,發現修改的行數比之前多,好像產生了幻覺一樣)
- 如何避免:設定隔離級別為serializable
演示前準備
用一張表account來演示,表字段只包括自增主鍵、name、money三個欄位。並且有三條資料。
CREATE TABLE account(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30) NOT NULL,
money INT(11) NOT NULL
);
INSERT INTO account(NAME, money) VALUES ('zhangsan', 1000);
INSERT INTO account(NAME, money) VALUES ('liuneng', 1000);
INSERT INTO account(NAME, money) VALUES ('zhaosi', 1000);
下面會多次用到查詢事務隔離級別的命令,在此先列出查詢事務隔離級別的命令:
SELECT @@tx_isolation;
髒讀
設定事務隔離級別為read uncommitted(讀未提交)
set session transaction isolation level read uncommitted;
原始資料:
1.開啟一個事務,並且修改id為1的money值-100
start transaction;
update account set money = money - 100 where id = 1;
2.開啟另外事務,查詢表
START TRANSACTION;
SELECT * FROM account;
已經表明能夠讀到另外一個事務未提交的資料了。我們在第二個事務給money+200,並且提交
UPDATE account SET money = money + 200 WHERE id = 1;
commit;
3.此時讓第一個session回滾事務,我們再次查詢表
ROLLBACK;
理論上我們第一次是無效的,所以本來1000加上200後是1200,但是因為髒讀,第二個事務是讀到了第一個事務未提交的資料上做的修改導致出問題。
避免髒讀:設定事務隔離級別為read committed(讀已提交)
不可重複讀
設定事務隔離級別為read committed(讀已提交)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
原始資料:
1.開啟一個事務,並且先查詢一下id為1的money
START TRANSACTION;
SELECT * FROM account WHERE id = 1;
2.開啟另外一個事務,給id為1的money+300,並提交
START TRANSACTION;
UPDATE account SET money = money + 300 WHERE id = 1;
COMMIT;
3.第一個事務再查資料
此時,第一個事務提交。
COMMIT;
提交後查詢表,發現第一個事務明明什麼都沒做,結果資料+300,此時如果事務一對資料修改,則會產生問題。
避免不可重複讀:設定事務隔離級別為repeatable read(可重複讀)
幻讀
設定事務隔離級別為repeatable read(可重複讀)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
原始資料:
1.同時開啟兩個事務AB
START TRANSACTION;
2.事務B插入一條資料,並且提交
INSERT INTO account(NAME, money) VALUES ('zhaoguangkun', 500);
COMMIT;
3.事務A修改所有的資料的money為2000,並且提交
UPDATE account SET money = 2000;
COMMIT;
對於事務A來說,本來是有3行資料的,修改所有的money後,竟然影響了4行,我們再來看看資料庫:
幻讀是好像出現了幻覺一樣,幻讀一般產生在插入/刪除資料。
避免幻讀:設定事務隔離級別為serializable(序列)