【Mysql進(jìn)階】數(shù)據(jù)庫(kù)之事務(wù)隔離機(jī)制

什么是事務(wù)(Transaction)

事務(wù)是指一組操作集合稚照,這一組操作執(zhí)行完成之后必須滿足 ACID 特性被啼。

  • 原子性(Atomic): 一組操作要么全部執(zhí)行成功盟迟,要么全部執(zhí)行失斞辜;
  • 一致性(Consistency): 事務(wù)執(zhí)行成功后骤坐,數(shù)據(jù)必須保持一致绪杏。例如轉(zhuǎn)賬事務(wù)下愈,不管有多少個(gè)轉(zhuǎn)賬并發(fā)纽绍,戶頭的錢款總數(shù)還是固定一致的;
  • 隔離性(Isolation): 并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離势似。串行處理事務(wù)能保證絕對(duì)的隔離拌夏,但考慮到性能的問(wèn)題,可以適當(dāng)降低隔離程度以提高并發(fā)效率履因;
  • 持久性(Duration): 事務(wù)執(zhí)行后障簿,對(duì)數(shù)據(jù)的影響是永久性的,即使系統(tǒng)出現(xiàn)故障也會(huì)繼續(xù)保持栅迄。

對(duì)于數(shù)據(jù)庫(kù)事務(wù)((Database Transaction)站故,這一組操作集合就是指多個(gè)SQL語(yǔ)句。這組SQL語(yǔ)句執(zhí)行時(shí)需要保證ACID的特性毅舆。

什么是事務(wù)隔離西篓?

一個(gè)事務(wù)要保證ACID的特性,事務(wù)隔離就是指其中的隔離性(Isolation)憋活。
隔離性越高岂津,系統(tǒng)吞吐量越低。

所以我們?cè)诳紤]事務(wù)隔離問(wèn)題時(shí)悦即,本質(zhì)上是在考慮一個(gè)trade off的問(wèn)題:

  • 隔離性
  • 吞吐量

事務(wù)隔離的級(jí)別

事務(wù)隔離的級(jí)別有四個(gè)級(jí)別:

  • Read Uncommitted
  • Read Committed
  • Repeatable Read
  • Serializable

這四個(gè)級(jí)別的主要區(qū)分在于:

一個(gè)事務(wù)執(zhí)行時(shí)能否讀取到其他事務(wù)對(duì)數(shù)據(jù)所做的修改吮成。

PS: 最好的理解事務(wù)隔離級(jí)別的方式就是從隔離方式的命名去理解。

第一級(jí)別:Read Uncommitted

Read Uncommitted辜梳,當(dāng)前事務(wù)讀取到其他未提交(uncommitted)的事務(wù)所做的數(shù)據(jù)更新粱甫。

這種現(xiàn)象通常也叫作 臟讀 (Dirty Read)

#首先作瞄,修改隔離級(jí)別
set tx_isolation='READ-UNCOMMITTED';
select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+

#事務(wù)A:?jiǎn)?dòng)一個(gè)事務(wù)
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)B:也啟動(dòng)一個(gè)事務(wù)(那么兩個(gè)事務(wù)交叉了)
#在事務(wù)B中執(zhí)行更新語(yǔ)句魔种,且不提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)A:那么這時(shí)候事務(wù)A能看到這個(gè)更新了的數(shù)據(jù)嗎?
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |   --->可以看到!說(shuō)明我們讀到了事務(wù)B還沒(méi)有提交的數(shù)據(jù)
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)B:事務(wù)B回滾,仍然未提交
rollback;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)A:在事務(wù)A里面看到的也是B沒(méi)有提交的數(shù)據(jù)
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |      --->臟讀意味著我在這個(gè)事務(wù)中(A中)粉洼,事務(wù)B雖然沒(méi)有提交节预,但它任何一條數(shù)據(jù)變化叶摄,我都可以看到!
|    2 |    2 |
|    3 |    3 |
+------+------+

第二級(jí)別:Read Committed

Read committed安拟,當(dāng)前事務(wù)讀取到其他已提交(committed)的事務(wù)所做的數(shù)據(jù)更新蛤吓。

該隔離級(jí)別會(huì)帶來(lái)另一個(gè)現(xiàn)象,不可重復(fù)讀(Non-repeatable Read)糠赦,是指一個(gè)事務(wù)執(zhí)行期間会傲,因?yàn)槠渌聞?wù)所做的數(shù)據(jù)更新,可能會(huì)存在多次讀取數(shù)據(jù)不一致的現(xiàn)象拙泽。

目前淌山,該級(jí)別通常是大部分?jǐn)?shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別。 Mysql是例外顾瞻,它的隔離級(jí)別是第三級(jí)別泼疑,后續(xù)會(huì)有介紹。

#首先修改隔離級(jí)別
set tx_isolation='read-committed';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+

#事務(wù)A:?jiǎn)?dòng)一個(gè)事務(wù)
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)B:也啟動(dòng)一個(gè)事務(wù)(那么兩個(gè)事務(wù)交叉了)
       在這事務(wù)中更新數(shù)據(jù)荷荤,且未提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)A:這個(gè)時(shí)候我們?cè)谑聞?wù)A中能看到數(shù)據(jù)的變化嗎?
select * from tx; --------------->
+------+------+                |
| id   | num  |                |
+------+------+                |
|    1 |    1 |--->并不能看到退渗!  |
|    2 |    2 |                |
|    3 |    3 |                |
+------+------+                |——>相同的select語(yǔ)句,結(jié)果卻不一樣
                               |
#事務(wù)B:如果提交了事務(wù)B呢?         |
commit;                        |
                               |
#事務(wù)A:                         |
select * from tx; --------------->
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |--->因?yàn)槭聞?wù)B已經(jīng)提交了蕴纳,所以在A中我們看到了數(shù)據(jù)變化
|    2 |    2 |
|    3 |    3 |
+------+------+

第三級(jí)別:Repeatable Read

Repeatable Read会油,當(dāng)前事務(wù)讀取不到其他事務(wù)所做的數(shù)據(jù)更新。事務(wù)執(zhí)行階段內(nèi)某段范圍內(nèi)的數(shù)據(jù)古毛,無(wú)論讀取多少次都是一樣(Repeatable)的翻翩。

該隔離級(jí)別存在另一個(gè)問(wèn)題,幻讀(Phantom Read), 是指事務(wù)執(zhí)行期間可能讀取到其他事務(wù)的新增數(shù)據(jù)的現(xiàn)象稻薇。 例如同一條SQL語(yǔ)句嫂冻,select * from table where id>10 ,第一次執(zhí)行讀出來(lái)5條颖低,第二次執(zhí)行可能讀出來(lái)6條絮吵。

目前,主流的數(shù)據(jù)庫(kù)(Mysql忱屑、Oracle)都通過(guò)多版本并發(fā)控制(MVCC蹬敲,Multiversion Concurrency Control)機(jī)制解決了該問(wèn)題。

#首先莺戒,更改隔離級(jí)別
set tx_isolation='repeatable-read';
select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

#事務(wù)A:?jiǎn)?dòng)一個(gè)事務(wù)
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)B:開(kāi)啟一個(gè)新事務(wù)(那么這兩個(gè)事務(wù)交叉了)
       在事務(wù)B中更新數(shù)據(jù)伴嗡,并提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+
commit;

#事務(wù)A:這時(shí)候即使事務(wù)B已經(jīng)提交了,但A能不能看到數(shù)據(jù)變化?
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 | --->還是看不到的从铲!(這個(gè)級(jí)別2不一樣瘪校,也說(shuō)明級(jí)別3解決了不可重復(fù)讀問(wèn)題)
|    2 |    2 |
|    3 |    3 |
+------+------+

#事務(wù)A:只有當(dāng)事務(wù)A也提交了,它才能夠看到數(shù)據(jù)變化
commit;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

第四級(jí)別:Serializable

Serializable,事務(wù)串行執(zhí)行阱扬,每次執(zhí)行事務(wù)都對(duì)相關(guān)的數(shù)據(jù)加鎖(一般來(lái)說(shuō)是共享鎖泣懊,其他事務(wù)可讀不可寫(xiě))。

該級(jí)別雖然不存在前面是三個(gè)級(jí)別提到的 臟讀麻惶、不可重復(fù)讀馍刮、幻讀等問(wèn)題,但同時(shí)由于存在大量的鎖競(jìng)爭(zhēng)窃蹋,會(huì)使得吞吐量下降卡啰。

#首先修改隔離界別
set tx_isolation='serializable';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+

#事務(wù)A:開(kāi)啟一個(gè)新事務(wù)
start transaction;

#事務(wù)B:在A沒(méi)有commit之前,這個(gè)交叉事務(wù)是不能更改數(shù)據(jù)的
start transaction;
insert tx values('4','4');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
update tx set num=10 where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

總結(jié)

這里寫(xiě)圖片描述

當(dāng)然警没,目前Repeatable Read級(jí)別也通過(guò)MVCC機(jī)制解決了幻讀的現(xiàn)象匈辱。

MVCC機(jī)制可以在不需要使用鎖的情況下完成并發(fā)讀寫(xiě),具體實(shí)現(xiàn)機(jī)制待更新杀迹。()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亡脸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子佛南,更是在濱河造成了極大的恐慌梗掰,老刑警劉巖嵌言,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗅回,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡摧茴,警方通過(guò)查閱死者的電腦和手機(jī)绵载,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)苛白,“玉大人娃豹,你說(shuō)我怎么就攤上這事」喝梗” “怎么了懂版?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)躏率。 經(jīng)常有香客問(wèn)我躯畴,道長(zhǎng),這世上最難降的妖魔是什么薇芝? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任蓬抄,我火速辦了婚禮,結(jié)果婚禮上夯到,老公的妹妹穿的比我還像新娘嚷缭。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布阅爽。 她就那樣靜靜地躺著路幸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪付翁。 梳的紋絲不亂的頭發(fā)上劝赔,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音胆敞,去河邊找鬼着帽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛移层,可吹牛的內(nèi)容都是我干的仍翰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼观话,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼予借!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起频蛔,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灵迫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后晦溪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瀑粥,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年三圆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狞换。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舟肉,死狀恐怖修噪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情路媚,我是刑警寧澤黄琼,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站整慎,受9級(jí)特大地震影響脏款,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜院领,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一弛矛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧比然,春花似錦丈氓、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)湾笛。三九已至,卻和暖如春闰歪,著一層夾襖步出監(jiān)牢的瞬間嚎研,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工库倘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留临扮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓教翩,卻偏偏與公主長(zhǎng)得像杆勇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饱亿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容