mysql 四種隔離級別分析

sql標準中,有四種隔離級別,各個離級別都有各自的規則,隔離級別越低,允許併發越大,消耗的資源越少,但是越不安全,下面就mysql數據庫來分別介紹一下(每個存儲引擎實施的隔離級別會有稍微的不同)
mysql 動態修改隔離級別的命令
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{
READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SERIALIZABLE
}

1:READ UNCOMMITTED
在這種隔離級別中,事務能看到其他事務未提交的結果,像這種讀到uncommitted的數據稱爲dirty read
如:
mysql--root@localhostnone) 06:47:49>>show variables like 'tx%';
+---------------+------------------+
| Variable_name | Value |
+---------------+------------------+
| tx_isolation | READ-UNCOMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)
session A session B
start TRANSACTION; start TRANSACTION;
select * from t4 where i>45; select * from t4 where i>45;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 2 | | 55 | 2 | 
| 46 | 2 | | 46 | 2 | 
| 47 | 3 | | 47 | 3 | 
| 48 | 2 | | 48 | 2 | 

insert into t4 values (49,4),(49,4); 
Query OK, 2 rows affected (0.00 sec) 
Records: 2 Duplicates: 0 Warnings: 0

select * from t4 where i>45;
+------+------+ 
| i | j | 
+------+------+ 
| 55 | 2 | 
| 46 | 2 | 
| 47 | 3 | 
| 48 | 2 | 
| 49 | 4 | 
| 49 | 4 | 
+------+------+ 
6 rows in set (0.00 sec) 


select * from t4 where i>45; 
+------+------+ 
| i | j | 
+------+------+ 
| 55 | 2 | 
| 46 | 2 | 
| 47 | 3 | 
| 48 | 2 | 
| 49 | 4 | 
| 49 | 4 | 

+------+------+ 
6 rows in set (0.00 sec) 


commit;
很明顯,在session A 中,未提交事務修改的數據,在session B中也能顯示,這樣就是未提交讀隔離級別
2:READ COMMITTED
在這種隔離級別下,事務只能看到其他事務commit的數據,但是在這種級別下,會出現所謂的”不可重複讀“問題,即查詢前後,得到的數據不一樣
如:
mysql--root@localhostnone) 07:02:03>>show variables like 'tx%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.00 sec)

session A session B

select * from t4 where i=55; select * from t4 where i=55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 2 | | 55 | 2 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec) 

update t4 set j=4 where i=55;
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

select * from t4 where i=55; select * from t4 where i=55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 4 | | 55 | 2 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec) 
在session B中是看不到未提交事務修改的數據

commit;

select * from t4 where i=55; select * from t4 where i=55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 4 | | 55 | 4 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec)
當事務提交後,session B 就能看到修改的數據,這樣也就發生了上述所謂的“不可重複讀”問題

3:REPEATABLE READ
理論上講,該級別解決了READ COMMITTED級別的“不可重複讀”問題,但是還是會出現所謂的“幽靈讀”問題,何謂“幽靈讀”,當你通過一區間查詢時候,其他事務在這期間插入一條數據並提交,這樣你在次查詢時,會發現突然多出一行,這就是所謂的“幽靈行”,但是對於innodb跟
falcon,他們通過MVCC解決了這個問題,故對於innodb 跟 falcon,實現了名副其實的可重複讀 

如:
show variables like 'tx%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
1)
session A session B
start TRANSACTION; start TRANSACTION;
select * from t4 where i=55; select * from t4 where i=55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 4 | | 55 | 4 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec)

update t4 set j=6 where i=55; 
commit; 

select * from t4 where i=55; select * from t4 where i=55; 
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 55 | 6 | | 55 | 4 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec)

像這次就沒有出現上一級別中不可能重複讀問題
2)
session A session B
start TRANSACTION; start TRANSACTION;
select * from t4 where i>47 and i<55; select * from t4 where i>47 and i<55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 48 | 2 | | 48 | 2 | 
+------+------+ +------+------+ 
1 row in set (0.00 sec) 1 row in set (0.00 sec) 

insert into t4 values (50,1); 
commit;

select * from t4 where i>47 and i<55; select * from t4 where i>47 and i<55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 48 | 2 | | 48 | 2 | 
| 50 | 1 | +------+------+ 
+------+------+ 1 row in set (0.00 sec) 
2 rows in set (0.00 sec) 

commit;
select * from t4 where i>47 and i<55;
+------+------+ 
| i | j | 
+------+------+ 
| 48 | 2 | 
| 50 | 1 | 
+------+------+ 
2 rows in set (0.00 sec) 
像這樣,沒有出現幽靈讀問題,就是真正的可持續讀了, 

4:SERIALIZABLE
最高級別,這一級別是強制事務順序執行,這樣就解決了以上可持續讀的問題,但是會出現大量的鎖等待與死鎖問題

1)
session A SESSION B
start TRANSACTION; start TRANSACTION;
insert into t4 values (52,4);

select * from t4 where i>48 and i<55;
等待中。。。。
commit 
+------+------+ 
| i | j | 
+------+------+ 
| 50 | 1 | 
| 51 | 4 | 
| 52 | 4 | 
+------+------+ 
3 rows in set (6.05 se
2) 
session A SESSION B 
start TRANSACTION; start TRANSACTION;

select * from t4 where i>50 and i<55; select * from t4 where i>48 and i<55;
+------+------+ +------+------+ 
| i | j | | i | j | 
+------+------+ +------+------+ 
| 51 | 4 | | 50 | 1 | 
| 52 | 4 | | 51 | 4 | 
+------+------+ | 52 | 4 | 
2 rows in set (0.00 sec) +------+------+ 
3 rows in set (0.00 sec) 


insert into t4 values (53,4); 
等待中 如執行insert 則出現死鎖,
session B ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
如 執行commit; session A 中insert 執行
這就是在innodb下,四種隔離級別的具體分析了。很明顯,根據自己的需要選擇何時的隔離級別,對於提升系統性能也有莫大的幫助

轉自:mysql中四種隔離級別的具體分析
http://bbs.linuxtone.org/thread-4781-1-1.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章