事務是應用程序中一系列嚴密的操做,全部的操做必須成功完成,不然每一個操做中國所作的全部更改都會被撤銷。也就是事務具備原子性,一個事務中的一系列的操做要麼所有成功,要麼一個都不作。mysql
事務的結束有兩種,當事務中的全部步驟所有成功執行時,事務提交。若是一個步驟失敗,將發生回滾操做,撤銷以前到事務開始時的全部操做。sql
事務具備四個特徵:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持續性(Durability)。這一個特性簡稱爲ACID特性。數據庫
事務操做:session
讀鎖(共享)併發
寫鎖(獨佔)性能
SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級通常支持更高的併發處理,並擁有更低的系統開銷。測試
Read Uncommitted(讀取未提交內容)3d
在該隔離級別,全部事物均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用。所以它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)code
Read Committed(讀取提交內容)blog
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別也支持所謂的不可重讀(NonRepeatable Read),由於同一個事務的其餘實例在該實例處理期間可能會有新的commit,因此統一Select可能返回不一樣的結果。
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到相同的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發生有新的「幻影」行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串行化)
這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,他是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。
這四種隔離級別採用不一樣的鎖類型來實現,若讀取的是同一份數據的話,就容易發生問題。
在MySQL中,實現了這四種隔離級別,分別有可能產生問題以下所示:
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
Read Uncommited | ✔ | ✔ | ✔ |
Read Comitted | ✘ | ✔ | ✔ |
Repeatable Read | ✘ | ✘ | ✔ |
Serializable | ✘ | ✘ | ✘ |
準備工做:
create table `customers`( `id` int(11) unsigned not null AUTO_INCREMENT, `name` varchar(32) not null default '0', primary key(`id`) )Engine=InnoDB AUTO_INCREMENT = 4 default charset=utf8; insert into test(num) values(`tom`); insert into test(num) values(`jerry`); insert into test(num) values(`anny`);
[A]
2.關閉自動提交
set autocommit = 0;
3.開啓事務
start transaction;
4.執行更新
update name set name ='jerry' where id =1;
[B]
1.設置b的隔離級別
set session transaction isolation level read uncommitted;
5.查詢客戶
select * from customers
具體操做:
[A機器]:開啓事務,執行更新
[B機器]:查詢全部數據
[A機器]:回滾事務
[B機器]:髒讀致使了數據不一致
解決:
6.[B機器]:隔離級別提高爲read committed;
set session transaction isolation level read committed
7.[A機器]:從新開啓事務,更新數據
8.[B機器]:查詢數據
[A]
設置隔離級別 read committed
set session transaction isolation level read committed;
關閉自動提交
set autocommit = 0;
開啓事務
start transaction;
查詢
select name from customers where id =1;
[B]
5.開啓事務,更新數據,提交數據(默認是自動提交)
update customers set names = 'jerry' where id =1
具體操做:
[A機器]:設置隔離級別,關閉自動提交,開啓事務,查詢數據
[B機器]:更新數據
[A機器]:再次查詢數據,發現數據已經被更新
解決:提高隔離級別到repeatbale read
[A機器]:設置隔離級別,關閉自動提交,開啓事務,查詢數據
若是遇到ERROR 1568,請commit以後再進行設置操做。
[B機器]:更新數據
[A機器]:查詢數據,發現數據沒有發生變化