開發工作中我們會使用到事務,那你們知道事務又分哪幾種嗎?
MYSQL標準定義了4類隔離級別,用來限定事務內外的哪些改變是可見的,哪些是不可見的。
低的隔離級一般支援更高的並發處理,並擁有更低的系統開銷。
隔離等級由低到高:Read Uncommitted Read Uncommitted(讀取未提交內容)
在該隔離級別,所有交易都可以看到其他未提交(commit)事務的執行結果。
本隔離等級很少用於實際應用,因為它的效能也不比其他等級好多少。
讀取未提交的數據,也稱為髒讀(Dirty Read)。 [窗口A]:<br>
<br>
mysql> set GLOBAL tx_isolation='READ-UNCOMMITTED';<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> quit;<br>
Bye<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> SELECT @@tx_isolation;<br>
+------------------+<br>
| @@tx_isolation |<br>
+------------------+<br>
| READ-UNCOMMITTED |<br>
+------------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> use test;<br>
Database changed<br>
mysql> begin;<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> select * from user;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 1 | a |<br>
| 2 | b |<br>
+----+------+<br>
2 rows in set (0.00 sec)<br>
<br>
[視窗B]:<br>
mysql> select @@tx_isolation;<br>
+------------------+<br>
| @@tx_isolation |<br>
+------------------+<br>
| READ-UNCOMMITTED |<br>
+------------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> begin;<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> insert into test.user values (3, 'c');<br>
Query OK, 1 row affected (0.00 sec)<br>
<br>
mysql> select * from user;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 1 | a |<br>
| 2 | b |<br>
| 3 | c |<br>
+----+------+<br>
3 rows in set (0.00 sec)<br>
<br>
//目前為止,視窗B並未commit;<br>
<br>
[窗口A]:<br>
mysql> select * from user ;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 1 | a |<br>
| 2 | b |<br>
| 3 | c |<br>
+----+------+<br>
3 rows in set (0.00 sec)
Read Committed(讀取提交內容)
這是大多數資料庫系統的預設隔離等級(但不是MySQL預設的)。
它滿足了隔離的簡單定義:一個交易只能看見已經提交事務所所做的改變。
這種隔離等級 也支援所謂的不可重複讀取(NonrepeatableRead),因為相同交易的其他實例在該實例處理其間可能會有新的commit,所以相同 select 可能會傳回不同結果。 [窗口A]:<br>
<br>
mysql> SET GLOBAL tx_isolation='READ-COMMITTED';<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> quit;<br>
Bye<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> SELECT @@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| READ-COMMITTED |<br>
+----------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> begin;<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> select * from test.user;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 1 | a |<br>
| 2 | b |<br>
+----+------+<br>
2 rows in set (0.00 sec)<br>
<br>
<br>
[視窗B]:<br>
<br>
mysql> SELECT @@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| READ-COMMITTED |<br>
+----------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> begin;<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 1 | 一個 |<br>
| 2|| b |<br>
+----+------+<br>
2 行一組(0.00 秒)<br>
<br>
mysql> 從 test.user 中刪除,其中 id=1;<br>
查詢正常,1 行受影響(0.00 秒)<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 2|| b |<br>
+----+------+<br>
一組 1 行(0.00 秒)<br>
<br>
[窗口A]:<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 1| 一個 |<br>
| 2|| b |<br>
+----+------+<br>
2 行一組(0.00 秒)<br>
<br>
[窗口B]:<br>
<br>
mysql> 提交;<br>
查詢正常,0 行受影響(0.02 秒)<br>
<br>
[窗口A]:<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 2|| b |<br>
+----+------+<br>
一組中 1 行(0.00 秒)
可重複讀取(可重讀)
這是MySQL的預設事務隔離級別,它確保相同事務的多個實例在讀取資料時,會看到相同的資料行。
從理論上講,這會導致另一個棘手的問題:幻讀(Phantom Read)。然而
簡單的說,幻讀指當使用者讀取該範圍的資料行時,另一個事務又在該範圍內插入了新行,使用者當再讀取該範圍的資料行時,會發現有新的「幻影”行。
InnoDB和Falcon儲存引擎透過多版本並發控制(MVCC,Multiversion Concurrency Control)機制解決了這個問題。 [窗口A]:<br>
<br>
mysql> SET GLOBAL tx_isolation='REPEATABLE-READ';<br>
查詢正常,0 行受影響(0.00 秒)<br>
<br>
mysql> 退出;<br>
再見<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> 選擇@@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| 可重複閱讀|<br>
+----------------+<br>
一組 1 行(0.00 秒)<br>
<br>
mysql> 開始;<br>
查詢正常,0 行受影響(0.00 秒)<br>
<br>
[窗口B]:<br>
<br>
mysql> 退出;<br>
再見<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> 選擇@@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| 可重複閱讀|<br>
+----------------+<br>
一組 1 行(0.00 秒)<br>
<br>
mysql> 插入 test.user 值 (4, 'd');<br>
查詢正常,1 行受影響(0.00 秒)<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 2|| b |<br>
| 4| d |<br>
+----+------+<br>
2 行一組(0.00 秒)<br>
<br>
[窗口A]:<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 2|| b |<br>
+----+------+<br>
1 行一組(0.00 秒)<br>
<br>
mysql> 提交;<br>
查詢正常,0 行受影響(0.00 秒)<br>
<br>
mysql> 從 test.user 中選擇 *;<br>
+----+------+<br>
| 編號| 名字|<br>
+----+------+<br>
| 2|| b |<br>
| 4| d |<br>
+----+------+<br>
2 rows in set (0.00 sec)
Serialized(序列化執行)
這是的隔離級別,它透過強制最高事務排序,使得不可能相互衝突,從而解決幻讀問題。
簡言之,它是在每個讀取的資料行上加上共享鎖定。在這個級別,可能導致大量的超時現象和鎖定競爭。 [窗口A]:<br>
<br>
mysql> SET GLOBAL tx_isolation='SERIALIZABLE';<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> quit;<br>
Bye<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> SELECT @@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| SERIALIZABLE |<br>
+----------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> select * from test.user;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 2 | b |<br>
| 4 | d |<br>
+----+------+<br>
2 rows in set (0.00 sec)<br>
<br>
mysql> begin;<br>
Query OK, 0 rows affected (0.00 sec)<br>
<br>
mysql> insert into test.user values (5, 'e');<br>
Query OK, 1 row affected (0.00 sec)<br>
<br>
[視窗B]:<br>
<br>
mysql> quit;<br>
Bye<br>
<br>
[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登入)<br>
<br>
mysql> SELECT @@tx_isolation;<br>
+----------------+<br>
| @@tx_isolation |<br>
+----------------+<br>
| SERIALIZABLE |<br>
+----------------+<br>
1 row in set (0.00 sec)<br>
<br>
mysql> select * from test.user;<br>
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction<br>
<br>
[窗口A]:<br>
<br>
mysql> commit;<br>
Query OK, 0 rows affected (0.01 sec)<br>
<br>
[視窗B]:<br>
<br>
mysql> mysql> select * from test.user;<br>
+----+------+<br>
| id | name |<br>
+----+------+<br>
| 2 | b |<br>
| 4 | d |<br>
| 5 | e |<br>
+----+------+<br>
3 rows in set (0.00 sec)
Thank ~
資料來源:http://mp.weixin.qq.com/s?__biz=MjM5NDM4MDIwNw==&mid=2448834642&idx=1&sn=c02c5cc8ab0c1f29142ac8f8aa6b78aff#rd
更多【乾貨分享】,請關注我的個人訂閱號碼。