mysql系列之(1)——事務(wù)和鎖

數(shù)據(jù)庫(kù)事務(wù)是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作窖张,要么完全執(zhí)行诈胜,要么完全地不執(zhí)行豹障。

事務(wù)必須具備ACID四個(gè)特性:
原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾焦匈。
一致性是指事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致的狀態(tài)變到另外一個(gè)一致的狀態(tài)血公,也就是執(zhí)行事務(wù)之前和之后的狀態(tài)都必須處于一致的狀態(tài)。
隔離性是指當(dāng)多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫(kù)時(shí)缓熟,比如操作同一張表時(shí)累魔,數(shù)據(jù)庫(kù)為每一個(gè)用戶開啟的事務(wù)摔笤,不能被其他事務(wù)的操作所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離垦写。
持久性是指一個(gè)事務(wù)一旦被提交了吕世,那么對(duì)于數(shù)據(jù)庫(kù)中的數(shù)據(jù)改變就是永久性的,即便是在數(shù)據(jù)庫(kù)系統(tǒng)遭遇到故障的情況下也不會(huì)丟失提交事務(wù)的操作梯投。

提交事務(wù):
>set autocommit = 0 禁止自動(dòng)提交
>start transaction;
>update accout set money=money+100 where name="Jason";
>commit;
回滾事務(wù):
>set autocommit = 0 禁止自動(dòng)提交
>start transaction;
>update account set money=money-100 where name="justin";
>rollback;

1命辖、事務(wù)的隔離級(jí)別

mysql修改事務(wù)的隔離級(jí)別
>set? [global | session]? transaction isolation level 隔離級(jí)別名稱;
>set tx_isolation=’隔離級(jí)別名稱;’
隔離級(jí)別:Serializable | Repeatable read | Read committed |Read uncommitted
設(shè)置默認(rèn)級(jí)別是指當(dāng)前session的下一個(gè)事務(wù)
設(shè)置session級(jí)別是指當(dāng)前session以后的所有事務(wù)
設(shè)置global級(jí)別是指對(duì)之后的所有session,不包括當(dāng)前session

四種隔離級(jí)別和可能產(chǎn)生的問題

不可重復(fù)讀:Read committed讀已提交事務(wù)的數(shù)據(jù)分蓖,可能是兩次查詢過程中間插入了一個(gè)事務(wù)更新的原有的數(shù)據(jù)尔艇,導(dǎo)致出現(xiàn)同一事務(wù)的不同實(shí)例先后讀取的內(nèi)容不同。在 Repeatable read通過數(shù)據(jù)庫(kù)事務(wù)版本號(hào)方式解決么鹤。
事務(wù)1:
mysql> begin;
Query OK, 0 rows affected

mysql> select * from student where stu_id = 2;
+----+------+--------+
| id | name | stu_id |
+----+------+--------+
|? 2 | 生物 |????? 2 |
+----+------+--------+
1 row in set
事務(wù)2:
mysql> begin;
Query OK, 0 rows affected

mysql> update student set name = '地理' where stu_id = 2;
Query OK, 1 row affected
Rows matched: 1? Changed: 1? Warnings: 0

mysql> commit;
Query OK, 0 rows affected
接下來事務(wù)1再次查詢:
mysql> select * from student where stu_id = 2;
+----+------+--------+
| id | name | stu_id |
+----+------+--------+
|? 2 | 地理 |????? 2 |
+----+------+--------+
1 row in set
上述過程可見终娃,帶事務(wù)1的一個(gè)事務(wù)中,兩次請(qǐng)求得到了不同的結(jié)果蒸甜,就導(dǎo)致了不可重復(fù)讀的現(xiàn)象棠耕。
幻讀:在一個(gè)事務(wù)的兩次查詢中數(shù)據(jù)筆數(shù)不一致,例如有一個(gè)事務(wù)查詢了幾列(Row)數(shù)據(jù)迅皇,而另一個(gè)事務(wù)卻在此時(shí)插入了新的幾列數(shù)據(jù)昧辽,先前的事務(wù)在接下來的查詢中,就會(huì)發(fā)現(xiàn)有幾列數(shù)據(jù)是它先前所沒有的登颓。
數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別是 Repeatable read搅荞。

2、鎖與事務(wù)

數(shù)據(jù)庫(kù)采用兩段鎖協(xié)議(Two-Phase Locking――2PL)

在對(duì)任何數(shù)據(jù)進(jìn)行讀框咙、寫操作之前咕痛,首先要申請(qǐng)并獲得對(duì)該數(shù)據(jù)的封鎖,即擴(kuò)展階段喇嘱。
在釋放一個(gè)封鎖之后茉贡,事務(wù)不再申請(qǐng)和獲得其它任何封鎖,即收縮階段者铜。
若所有事務(wù)均遵守兩段鎖協(xié)議腔丧,則這些事務(wù)的所有交叉調(diào)度都是可串行化的。

mysql的讀操作作烟,通常是不會(huì)加鎖的(和隔離機(jī)制有關(guān))愉粤,也就是說通常的讀操作是不加鎖的,而是通過mvcc去解決的拿撩,對(duì)于通常的寫請(qǐng)求衣厘,insert、update、delete通常會(huì)加行鎖影暴、間隙鎖或表鎖(這和索引是有關(guān)系的)错邦,這些鎖通常是排他的,會(huì)阻塞其他的事務(wù)寫事務(wù)型宙。具體的情況需要結(jié)合隔離機(jī)制撬呢。

(1)、鎖的類型:
共享鎖(S Lock)和排他鎖(X Lock)

意向共享鎖(IS Lock):事務(wù)想要獲取一張表中的某幾行共享鎖早歇。

意向排他鎖(IX Lock):事務(wù)想要獲取一張表中的某幾行的排它鎖倾芝。

表鎖:
對(duì)一整張表加鎖,并發(fā)能力低下(即使有分讀鎖箭跳、寫鎖)晨另,一般在DDL處理時(shí)使用。
行鎖:
只鎖住特定行的數(shù)據(jù)谱姓,并發(fā)能力強(qiáng)借尿,MySQL一般都是用行鎖來處理并發(fā)事務(wù)。

在更新記錄的時(shí)候會(huì)對(duì)此記錄加行鎖屉来,在事務(wù)沒有commit之前不會(huì)釋放鎖路翻,所以事務(wù)2的更新會(huì)阻塞等待事務(wù)1的排它鎖,當(dāng)事務(wù)1Commit后茄靠,行鎖釋放事務(wù)2獲得行鎖,更新成功掉冶。
Gap鎖(間隙鎖):
是MySQL使用索引對(duì)行鎖兩邊的區(qū)間進(jìn)行加鎖战秋,避免其他事務(wù)在這兩個(gè)區(qū)間insert的一種鎖癣蟋。


如圖所示:數(shù)據(jù)庫(kù)中存在值5,30尝哆。那么數(shù)據(jù)庫(kù)會(huì)將數(shù)據(jù)段切分以下幾個(gè)區(qū)間:
(negative infinity, 5],(5,30],(30,positive infinity)
select * from table where number=30 for update琐馆;
當(dāng)對(duì)值為30這一行加行鎖的時(shí)候歧胁,會(huì)同時(shí)對(duì)(5,30]和(30,positive infinity)加GAP鎖。這樣其他事務(wù)如果想在這兩個(gè)區(qū)間進(jìn)行insert操作的時(shí)候,需要等待本次事務(wù)完成。如果對(duì)不存在的數(shù)據(jù)進(jìn)行更新,比如更新20(不存在)對(duì)應(yīng)數(shù)據(jù)行,那么數(shù)據(jù)庫(kù)也會(huì)對(duì)其存在的區(qū)間(5,30]加GAP鎖。
Next-Key鎖:
Next-Key鎖是行鎖和GAP鎖的合并(MySQL使用它來避免幻讀)。
當(dāng)按照id(非唯一索引,不是主鍵)進(jìn)行更新或刪除的時(shí)候會(huì)先對(duì)id索引進(jìn)行next_key鎖瓦糟,防止幻讀,因?yàn)樾略黾拥挠涗浿荒茉?0的左邊和30的右邊或者就是30陆淀。那么鎖住范圍后就能保證防止“幻讀”。
注意:如果用到無索引的字段衅胀,那么MySQL會(huì)在存儲(chǔ)引擎層面將所有的記錄加鎖,然后由MySQL Server過濾哀九,如果不滿足會(huì)調(diào)用unlock_row把不滿足條件的記錄釋放鎖(這里違背了二段鎖協(xié)議)剿配。

(2)、Mvcc(多版本并發(fā)控制):
Mvcc是多版本的并發(fā)控制協(xié)議阅束,Innodb中的樂觀鎖實(shí)現(xiàn)呼胚。讀不加鎖,讀寫不沖突息裸。通過它提高M(jìn)ySQL的讀取操作的性能蝇更。并能解決MySQL的重復(fù)讀問題。
MVVC在每一行記錄的后面加兩個(gè)隱含列(記錄創(chuàng)建版本號(hào)和刪除版本號(hào))呼盆。這里的版本號(hào)指的是事務(wù)的版本號(hào)(每個(gè)事務(wù)啟動(dòng)的時(shí)候年扩,都有一個(gè)遞增的版本號(hào))。在更新時(shí)進(jìn)行版本號(hào)的遞增访圃,插入時(shí)新建一個(gè)版本號(hào)厨幻,同時(shí)舊版本數(shù)據(jù)存儲(chǔ)在undo日志中。
? ● 比如插入一條記錄(事務(wù)id為1)


? ● 如果把這條記錄name更新為dog



在更新操作的時(shí)候腿时,采用的是先標(biāo)記舊的那行記錄為已刪除况脆,并且刪除版本號(hào)是事務(wù)版本號(hào),然后插入一行新的記錄的方式批糟。


? ● 刪除這條記錄時(shí)



刪除操作的時(shí)候格了,就把事務(wù)版本號(hào)作為刪除版本號(hào)


執(zhí)行查詢操作需要符合如下規(guī)則才能被查出來


1) 刪除版本號(hào) 大于 當(dāng)前事務(wù)版本號(hào),就是說刪除操作是在當(dāng)前事務(wù)啟動(dòng)之后做的徽鼎。


2) 創(chuàng)建版本號(hào) 小于或者等于 當(dāng)前事務(wù)版本號(hào) 盛末,就是說記錄創(chuàng)建是在事務(wù)中(等于的情況)或者事務(wù)啟動(dòng)之前弹惦。

mvcc分為快照讀和當(dāng)前讀。
快照讀只是針對(duì)于目標(biāo)數(shù)據(jù)的版本小于等于當(dāng)前事務(wù)的版本號(hào)悄但,也就是說讀數(shù)據(jù)的時(shí)候可能讀到舊的數(shù)據(jù)肤频,但是這種快照讀不需要加鎖,性能很高算墨。
當(dāng)前讀是讀取當(dāng)前數(shù)據(jù)的最新版本,但是更新等操作會(huì)對(duì)數(shù)據(jù)進(jìn)行加鎖汁雷,所以當(dāng)前讀需要獲取記錄的行鎖净嘀,存在鎖爭(zhēng)用的問題。
下面是快照讀和當(dāng)前讀的常見操作:
快照讀:就是select * from table ....;
當(dāng)前讀:特殊的讀操作(加共享鎖或排他鎖)侠讯,插入/更新/刪除操作挖藏,需要加鎖。
select from table where ? lock in share mode;
select from table where ? for update;
其實(shí)Mysql實(shí)現(xiàn)的Mvcc并不純粹厢漩,因?yàn)樵诋?dāng)前讀的時(shí)候需要對(duì)記錄進(jìn)行加鎖膜眠,而不是多版本競(jìng)爭(zhēng)。下面是具體操作時(shí)的Mvcc機(jī)制:
? 1. SELECT時(shí)溜嗜,讀取創(chuàng)建版本號(hào)<=當(dāng)前事務(wù)版本號(hào)宵膨,刪除版本號(hào)為空或>當(dāng)前事務(wù)版本號(hào)。
? 2. INSERT時(shí)炸宵,保存當(dāng)前事務(wù)版本號(hào)為行的創(chuàng)建版本號(hào)
? 3. DELETE時(shí)辟躏,保存當(dāng)前事務(wù)版本號(hào)為行的刪除版本號(hào)
? 4. UPDATE時(shí),插入一條新紀(jì)錄土全,保存當(dāng)前事務(wù)版本號(hào)為行創(chuàng)建版本號(hào)捎琐,同時(shí)保存當(dāng)前事務(wù)版本號(hào)到原來刪除的行

總結(jié):
RC提交讀,采用行鎖和MVCC的當(dāng)前讀裹匙,有幻讀和不可重復(fù)讀問題瑞凑。RR可重讀,采用Next-key(默認(rèn))和MVCC的快照讀概页,無幻讀和可重復(fù)讀籽御。
mysql的鎖機(jī)制和事務(wù)隔離級(jí)別有關(guān)。并不是說所有的讀操作都不加鎖绰沥,寫操作加鎖篱蝇,加什么鎖也和索引類型、有無索引有關(guān)徽曲。

感謝分享:
http://www.reibang.com/p/bcc614524024
http://www.reibang.com/p/edbe22beaecb

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末零截,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秃臣,更是在濱河造成了極大的恐慌涧衙,老刑警劉巖哪工,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弧哎,居然都是意外死亡雁比,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門撤嫩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偎捎,“玉大人,你說我怎么就攤上這事序攘≤钏” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵程奠,是天一觀的道長(zhǎng)丈牢。 經(jīng)常有香客問我,道長(zhǎng)瞄沙,這世上最難降的妖魔是什么己沛? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮距境,結(jié)果婚禮上申尼,老公的妹妹穿的比我還像新娘。我一直安慰自己肮疗,他們只是感情好晶姊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伪货,像睡著了一般们衙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碱呼,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天蒙挑,我揣著相機(jī)與錄音,去河邊找鬼愚臀。 笑死忆蚀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姑裂。 我是一名探鬼主播馋袜,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼舶斧!你這毒婦竟也來了欣鳖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茴厉,失蹤者是張志新(化名)和其女友劉穎泽台,沒想到半個(gè)月后什荣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怀酷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年稻爬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜕依。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桅锄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出样眠,到底是詐尸還是另有隱情竞滓,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布吹缔,位于F島的核電站,受9級(jí)特大地震影響锯茄,放射性物質(zhì)發(fā)生泄漏厢塘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一肌幽、第九天 我趴在偏房一處隱蔽的房頂上張望晚碾。 院中可真熱鬧,春花似錦喂急、人聲如沸格嘁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)糕簿。三九已至,卻和暖如春狡孔,著一層夾襖步出監(jiān)牢的瞬間懂诗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工苗膝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留殃恒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓辱揭,卻偏偏與公主長(zhǎng)得像离唐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子问窃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • 昨天了解了下數(shù)據(jù)庫(kù)中的事務(wù)的特性亥鬓,和事務(wù)隔離的級(jí)別。但是一覺醒來反復(fù)思考感覺對(duì)事務(wù)的隔離級(jí)別理解的不是很深入和透徹...
    MentallyL閱讀 1,059評(píng)論 0 9
  • 為了充分發(fā)揮MySQL的性能并順利地使用泡躯,就必須理解其設(shè)計(jì)贮竟。MySQL的靈活性體現(xiàn)在很多方面丽焊。例如,你可以通過配置...
    李文文丶閱讀 1,163評(píng)論 0 4
  • 什么是事務(wù) 事務(wù)是一條或多條數(shù)據(jù)庫(kù)操作語(yǔ)句的組合咕别,具備ACID技健,4個(gè)特點(diǎn)。 原子性:要不全部成功惰拱,要不全部撤銷 隔...
    jiangmo閱讀 1,080評(píng)論 0 3
  • 1背景1 1.1MVCC:Snapshot Read vs Current Read2 1.2Cluster In...
    簡(jiǎn)小鹿奔跑ing閱讀 4,145評(píng)論 1 50
  • 《摔跤吧偿短!爸爸》講的是印度一個(gè)全國(guó)摔跤冠軍爸爸欣孤,畢生的夢(mèng)想,就是為國(guó)爭(zhēng)光昔逗,站到世界的領(lǐng)臺(tái)上降传,.然而他因生活所...
    伏羲媽媽劉金梅閱讀 392評(píng)論 0 0