如上圖,四種隔離級別分別實現(xiàn)了不同的功能,看是級別越高也代表著需要的鎖越多,更容易產(chǎn)生阻塞。
接下來通過實驗介紹這幾種讀
(1)臟讀
把隔離級別調(diào)為READ-UNCOMMITTED
root@localhost:MySQL.sock 01:30:05 [(none)]>set global tx_isolation = 'READ-UNCOMMITTED';
root@localhost:mysql.sock 01:30:22 [(none)]>show global variables like '%iso%';
+---------------+------------------+
| Variable_name | Value |
+---------------+------------------+
| tx_isolation | READ-UNCOMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)
會話1:
root@localhost:mysql.sock 01:34:06 [lala]>select * from score;
Empty set (0.00 sec)
root@localhost:mysql.sock 01:34:53 [lala]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql.sock 01:35:23 [lala]>insert into score values(1,'xiaohong',99);
Query OK, 1 row affected (0.00 sec)
還沒有提交
會話2:
root@localhost:mysql.sock 01:37:08 [lala]>select * from score;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | xiaohong | 99 |
+------+----------+-------+
1 row in set (0.00 sec)
會話2可以直接讀到會話1還沒有提交的數(shù)據(jù)。
(2)不可重復讀
root@localhost:mysql.sock 01:30:05 [(none)]>set global tx_isolation = 'READ-COMMITTED';
root@localhost:mysql.sock 01:30:22 [(none)]>show global variables like '%iso%';
+---------------+------------------+
| Variable_name | Value |
+---------------+------------------+
| tx_isolation | READ-COMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)
會話1:
root@localhost:mysql.sock 01:49:00 [lala]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql.sock 01:49:08 [lala]>update score set id=3;
Query OK, 1 row affected (0.00 sec)
會話2:
root@localhost:mysql.sock 01:49:14 [lala]>select * from score;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | xiaohong | 99 |
+------+----------+-------+
1 row in set (0.00 sec)
會話1:
root@localhost:mysql.sock 01:49:20 [lala]>commit;
Query OK, 0 rows affected (0.00 sec)
會話2:
root@localhost:mysql.sock 01:49:47 [lala]>select * from score;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 3 | xiaohong | 99 |
+------+----------+-------+
1 row in set (0.00 sec)
會話2第一次只讀到id的值是1,但以為會話1提交,會話2第二次讀到id的值是3.
(3)幻讀
會話1:
root@localhost:mysql.sock 01:49:00 [lala]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql.sock 01:49:08 [lala]>insert into score values(2,'xiaoming',65);
Query OK, 1 row affected (0.00 sec)
會話2:
root@localhost:mysql.sock 01:49:14 [lala]>select * from score;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 1 | xiaohong | 99 |
+------+----------+-------+
1 row in set (0.00 sec)
會話1:
root@localhost:mysql.sock 01:49:20 [lala]>commit;
Query OK, 0 rows affected (0.00 sec)
會話2:
root@localhost:mysql.sock 01:50:27 [lala]>select * from score;
+------+----------+-------+
| id | name | score |
+------+----------+-------+
| 3 | xiaohong | 99 |
| 2 | xiaoming | 65 |
+------+----------+-------+
2 rows in set (0.00 sec)
會話2第一次只讀到1條數(shù)據(jù),但以為會話1提交,會話2第二次讀到兩條記錄
ps:不可重復讀是因為數(shù)據(jù)的update導致,而幻讀是因為數(shù)據(jù)的delete或者insert導致
mysql中的innodb的事務默認隔離級別是Repeatable read(可重復讀),但是它不是普通的Repeatable read,它在可重復讀的基礎上避免了幻讀。是通過臭名昭著的gop鎖實現(xiàn)不可重復讀。
root@localhost:mysql.sock 01:17:04 [(none)]>show global variables like '%iso%';