前言
在數(shù)據(jù)庫操作中,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級別。數(shù)據(jù)庫事務(wù)的隔離級別有4個,下面話不多說了,來一起看看詳細(xì)的介紹吧。
數(shù)據(jù)庫事務(wù)有四種隔離級別:
未提交讀(Read Uncommitted):允許臟讀,也就是可能讀取到其他會話中未提交事務(wù)修改的數(shù)據(jù)。 提交讀(Read Committed):只能讀取到已經(jīng)提交的數(shù)據(jù),Oracle等多數(shù)數(shù)據(jù)庫默認(rèn)都是該級別。 可重復(fù)讀(Repeated Read):可重復(fù)讀。在同一個事務(wù)內(nèi)的查詢都是事務(wù)開始時刻一致的,InnoDB默認(rèn)級別。在SQL標(biāo)準(zhǔn)中,該隔離級別消除了不可重復(fù)讀,但是還存在幻讀。 串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞。上面這樣的教科書式定義第一次接觸事務(wù)隔離概念的朋友看了可能會一臉懵逼,下面我們就通過具體的實例來解釋四個隔離級別。
首先我們創(chuàng)建一個user表:
| CREATE TABLE user ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE `uniq_name` USING BTREE (name)) ENGINE=`InnoDB` AUTO_INCREMENT=10 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; |
讀未提交隔離級別
我們先將事務(wù)的隔離級別設(shè)置為read committed:
| mysql> set session transaction isolation level read uncommitted;Query OK, 0 rows affected (0.00 sec)mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| READ-UNCOMMITTED |+------------------------+1 row in set (0.00 sec) |
在下面我們開了兩個終端分別用來模擬事務(wù)一和事務(wù)二,p.s: 操作一和操作二的意思是按照時間順序來執(zhí)行的。
事務(wù)1
| mysql> start transaction; # 操作1Query OK, 0 rows affected (0.00 sec)mysql> insert into user(name) values('ziwenxie'); # 操作3Query OK, 1 row affected (0.05 sec) |
事務(wù)2
| mysql> start transaction; # 操作2Query OK, 0 rows affected (0.00 sec)mysql> select * from user; # 操作4+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec) |
從上面的執(zhí)行結(jié)果可以很清晰的看出來,在read uncommited級別下面我們在事務(wù)一中可能會讀取到事務(wù)二中沒有commit的數(shù)據(jù),這就是臟讀。
讀提交隔離級別
通過設(shè)置隔離級別為committed可以解決上面的臟讀問題。
| mysql> set session transaction isolation level read committed; |
事務(wù)一
| mysql> start transaction; # 操作一Query OK, 0 rows affected (0.00 sec)mysql> select * from user; # 操作三+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec)mysql> select * from user; # 操作五,操作四的修改并沒有影響到事務(wù)一+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec)mysql> select * from user; # 操作七+----+------+| id | name |+----+------+| 10 | lisi |+----+------+1 row in set (0.00 sec)mysql> commit; # 操作八Query OK, 0 rows affected (0.00 sec) |