開發工做中咱們會使用到事務,那大家知道事務又分哪幾種嗎?mysql
MYSQL標準定義了4類隔離級別,用來限定事務內外的哪些改變是可見的,哪些是不可見的。sql
低的隔離級通常支持更高的併發處理,並擁有更低的系統開銷。
隔離級別由低到高:Read Uncommitted < Read Committed < Repeatable Read < Serializable。數據庫
Read Uncommitted(讀取未提交內容)
在該隔離級別,全部事務均可以看到其餘未提交(commit)事務的執行結果。
本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。
讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。centos
[窗口A]: mysql> set GLOBAL tx_isolation='READ-UNCOMMITTED'; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec) mysql> use test; Database changed mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | +----+------+ 2 rows in set (0.00 sec) [窗口B]: mysql> select @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into test.user values (3, 'c'); Query OK, 1 row affected (0.00 sec) mysql> select * from user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | | 3 | c | +----+------+ 3 rows in set (0.00 sec) //目前爲止,窗口B並未commit; [窗口A]: mysql> select * from user ; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | | 3 | c | +----+------+ 3 rows in set (0.00 sec)
Read Committed(讀取提交內容)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。
它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。
這種隔離級別 也支持所謂的不可重複讀(NonrepeatableRead),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一 select 可能返回不一樣結果。併發
[窗口A]: mysql> SET GLOBAL tx_isolation='READ-COMMITTED'; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | +----+------+ 2 rows in set (0.00 sec) [窗口B]: mysql> SELECT @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | +----+------+ 2 rows in set (0.00 sec) mysql> delete from test.user where id=1; Query OK, 1 row affected (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | +----+------+ 1 row in set (0.00 sec) [窗口A]: mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | +----+------+ 2 rows in set (0.00 sec) [窗口B]: mysql> commit; Query OK, 0 rows affected (0.02 sec) [窗口A]: mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | +----+------+ 1 row in set (0.00 sec)
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。
不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。
簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。
InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。性能
[窗口A]: mysql> SET GLOBAL tx_isolation='REPEATABLE-READ'; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) [窗口B]: mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) mysql> insert into test.user values (4, 'd'); Query OK, 1 row affected (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | | 4 | d | +----+------+ 2 rows in set (0.00 sec) [窗口A]: mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | +----+------+ 1 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | | 4 | d | +----+------+ 2 rows in set (0.00 sec)
Serializable(序列化執行)
這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。
簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。ui
[窗口A]: mysql> SET GLOBAL tx_isolation='SERIALIZABLE'; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set (0.00 sec) mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | | 4 | d | +----+------+ 2 rows in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into test.user values (5, 'e'); Query OK, 1 row affected (0.00 sec) [窗口B]: mysql> quit; Bye [root@vagrant-centos65 ~]# mysql -uroot -pxxxx(從新登陸) mysql> SELECT @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set (0.00 sec) mysql> select * from test.user; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction [窗口A]: mysql> commit; Query OK, 0 rows affected (0.01 sec) [窗口B]: mysql> mysql> select * from test.user; +----+------+ | id | name | +----+------+ | 2 | b | | 4 | d | | 5 | e | +----+------+ 3 rows in set (0.00 sec)