自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官問(wèn)我MVCC,我笑了

數(shù)據(jù)庫(kù) MySQL
mysql的默認(rèn)存儲(chǔ)引擎是innodb,該引擎是默認(rèn)支持事務(wù)以及事務(wù)的回滾,事務(wù)就是通過(guò)各種讀寫(xiě)鎖來(lái)實(shí)現(xiàn)的,那么讀寫(xiě)鎖就涉及到讀鎖和寫(xiě)鎖之間的沖突.

面試官:平時(shí)用的數(shù)據(jù)庫(kù)有哪些呢

表妹:親愛(ài)

mysql的默認(rèn)存儲(chǔ)引擎是innodb,該引擎是默認(rèn)支持事務(wù)以及事務(wù)的回滾

事務(wù)就是通過(guò)各種讀寫(xiě)鎖來(lái)實(shí)現(xiàn)的,那么讀寫(xiě)鎖就涉及到讀鎖和寫(xiě)鎖之間的沖突

而innodb為了提高讀取的效率,增加了MVCC多版本并發(fā)控制來(lái)更高效率的支持mysql中的讀取

事務(wù)

SQL語(yǔ)言共分為四大類(lèi)

數(shù)據(jù)查詢語(yǔ)言DQL,數(shù)據(jù)操縱語(yǔ)言DML,數(shù)據(jù)定義語(yǔ)言DDL,數(shù)據(jù)控制語(yǔ)言DCL。

1. 數(shù)據(jù)查詢語(yǔ)言DQL:數(shù)據(jù)查詢語(yǔ)言DQL基本結(jié)構(gòu)是由SELECT子句,F(xiàn)ROM子句,WHERE

2 .數(shù)據(jù)操縱語(yǔ)言DML:數(shù)據(jù)操縱語(yǔ)言DML主要有三種形式,插入,更新,刪除。

3. 數(shù)據(jù)定義語(yǔ)言DDL:數(shù)據(jù)定義語(yǔ)言DDL用來(lái)創(chuàng)建數(shù)據(jù)庫(kù)中的各種對(duì)象如:表 視圖 索引 同義詞 簇。DDL操作是隱性提交的,不能rollback

4. 數(shù)據(jù)控制語(yǔ)言DCL:數(shù)據(jù)控制語(yǔ)言DCL用來(lái)授予或回收訪問(wèn)數(shù)據(jù)庫(kù)的某種特權(quán),并控制數(shù)據(jù)庫(kù)操縱事務(wù)發(fā)生的時(shí)間及效果,對(duì)數(shù)據(jù)庫(kù)實(shí)行監(jiān)視等。

事務(wù)

事務(wù)指的是一組SQL語(yǔ)句,要么全部執(zhí)行成功,要么全部執(zhí)行失敗,要么提交,要么回滾,這句話大家聽(tīng)得耳朵都長(zhǎng)繭子了吧

事務(wù)特性ACID

原子性:事務(wù)是最小單元,不可再分,要么全部執(zhí)行成功,要么全部失敗回滾。

一致性:一致性是指事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致的狀態(tài)變到另外一個(gè)一致的狀態(tài),也就是執(zhí)行事務(wù)之前和之后的狀態(tài)都必須處于一致的狀態(tài)。不一致性包含三點(diǎn):臟讀,不可重復(fù)讀,幻讀

隔離性:隔離性是指當(dāng)多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),比如操作同一張表時(shí),數(shù)據(jù)庫(kù)為每一個(gè)用戶開(kāi)啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離

持久性:一旦事務(wù)提交,則其所做的修改將會(huì)永遠(yuǎn)保存到數(shù)據(jù)庫(kù)中。即使系統(tǒng)發(fā)生崩潰,事務(wù)執(zhí)行的結(jié)果也不能丟。

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

未提交讀:即能夠讀取到?jīng)]有被提交的數(shù)據(jù),所以很明顯這個(gè)級(jí)別的隔離機(jī)制無(wú)法解決臟讀、不可重復(fù)讀、幻讀中的任何一種。

已提交讀:即能夠讀到那些已經(jīng)提交的數(shù)據(jù),自然能夠防止臟讀,但是無(wú)法限制不可重復(fù)讀和幻讀

可重復(fù)讀:讀取了一條數(shù)據(jù),這個(gè)事務(wù)不結(jié)束,別的事務(wù)就不可以改這條記錄,這樣就解決了臟讀、不可重復(fù)讀的問(wèn)題,

串行化:多個(gè)事務(wù)時(shí),只有運(yùn)行完一個(gè)事務(wù)之后,才能運(yùn)行其他事務(wù)。

隔離級(jí)別問(wèn)題詳解

臟讀:一個(gè)事務(wù)處理過(guò)程里讀取了另一個(gè)未提交的事務(wù)中的數(shù)據(jù)

不可重復(fù)讀:一個(gè)事務(wù)在它運(yùn)行期間,兩次查找相同的表,出現(xiàn)了不同的數(shù)據(jù)

幻讀:在一個(gè)事務(wù)中讀取到了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后不一致

和不可重復(fù)讀的區(qū)別,這里是新增,不可重復(fù)讀是更改(或刪除)。

這兩種情況對(duì)策是不一樣的,對(duì)于不可重復(fù)讀,只需要采取行級(jí)鎖防止該記錄數(shù)據(jù)被更改或刪除,然而對(duì)于幻讀必須加表級(jí)鎖,防止在這個(gè)表中新增一條數(shù)據(jù)。

再議鎖和事務(wù)問(wèn)題

相信大家讀到這里,應(yīng)該也大致對(duì)鎖和事務(wù)的關(guān)系有了更進(jìn)一步的理解了吧,不清楚鎖的同學(xué)趕緊去mysql鎖的那一篇看看

來(lái),給大家捋一捋

共享鎖,也就是讀鎖,對(duì)一行數(shù)據(jù)加上共享鎖之后,別的事務(wù)就無(wú)法獲得該行數(shù)據(jù)的排他鎖了,別的事務(wù)也就暫時(shí)無(wú)法對(duì)這個(gè)數(shù)據(jù)進(jìn)行修改操作了,也就避免了不可重復(fù)讀這個(gè)問(wèn)題

排他鎖,也就是寫(xiě)鎖,一個(gè)事務(wù)對(duì)數(shù)據(jù)進(jìn)行修改的時(shí)候,就獲得相應(yīng)數(shù)據(jù)的寫(xiě)鎖,這時(shí)候別的事務(wù)也就無(wú)法獲得該數(shù)據(jù)的讀鎖和寫(xiě)鎖了,也就避免了臟讀問(wèn)題

臨鍵鎖的主要目的,也是為了避免幻讀(Phantom Read)。如果把事務(wù)的隔離級(jí)別降級(jí)為RC,臨鍵鎖則也會(huì)失效。

MVCC多版本并發(fā)控制

什么是MVCC

全稱Multi-Version Concurrency Control,多版本并發(fā)控制,屬于一種并發(fā)控制的手段,一般在數(shù)據(jù)庫(kù)管理系統(tǒng)中,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的并發(fā)訪問(wèn)

數(shù)據(jù)庫(kù)就必然涉及到讀和寫(xiě)的存在,讀寫(xiě)就必然涉及到讀寫(xiě)沖突,MVCC在mysql中的innodb引擎實(shí)現(xiàn)就是為了更好的解決讀寫(xiě)沖突,提高數(shù)據(jù)庫(kù)的性能,做到即使有讀寫(xiě)沖突的時(shí)候,也可以不用加鎖的方式,非阻塞方式來(lái)實(shí)現(xiàn)并發(fā)讀

最早的數(shù)據(jù)庫(kù)系統(tǒng),只有讀讀之間可以并發(fā),讀寫(xiě),寫(xiě)讀,寫(xiě)寫(xiě)都要阻塞。引入多版本之后,只有寫(xiě)寫(xiě)之間相互阻塞,其他三種操作都可以并行,這樣大幅度提高了InnoDB的并發(fā)度

MVCC只在 READ COMMITTED 和 REPEATABLE READ 兩個(gè)隔離級(jí)別下工作。其他兩個(gè)隔離級(jí)別夠和MVCC不兼容, 因?yàn)镽EAD UNCOMMITTED 總是讀取最新的數(shù)據(jù)行, 而不是符合當(dāng)前事務(wù)版本的數(shù)據(jù)行。而SERIALIZABLE 則會(huì)對(duì)所有讀取的行都加鎖

MVCC屬于一種悲觀鎖的實(shí)現(xiàn)

當(dāng)前讀和快照讀

當(dāng)前讀:像select lock in share mode這是共享鎖,select for update , update , insert , delete都是屬于排他鎖,上面說(shuō)的采用共享鎖和排他鎖的這種方式,都是屬于當(dāng)前讀,當(dāng)前讀就是讀取的記錄的最新版本,讀取的時(shí)候還會(huì)保證其他并發(fā)事務(wù)不會(huì)修改當(dāng)前的記錄,會(huì)對(duì)當(dāng)前的記錄進(jìn)行加鎖,防止修改

快照讀:不加鎖的正常的select查詢都是屬于快照讀,也就是不加鎖的非阻塞讀。

當(dāng)然,快照讀的前提是隔離級(jí)別不是串行級(jí)別,此時(shí)便會(huì)退化成當(dāng)前讀,之所以出現(xiàn)快照讀的情況,是mysql中的innodb引擎基于提高并發(fā)性能的考慮,快照讀也就是基本多版本的并發(fā)控制,來(lái)更高效的解決讀和寫(xiě)之間的沖突問(wèn)題

根據(jù)業(yè)務(wù)場(chǎng)景來(lái)考慮可以接受的問(wèn)題,避免了加鎖的操作,降低了開(kāi)銷(xiāo),既然是多版本并發(fā)控制,那么就要接受讀取到的并不一定是最新版本的歷史數(shù)據(jù)這一場(chǎng)景

實(shí)現(xiàn)

MVCC只是一個(gè)抽象概念,innodb實(shí)現(xiàn)這個(gè)靠的是三個(gè)隱式字段、undo log日志、Read View來(lái)實(shí)現(xiàn)的

三個(gè)隱式字段

數(shù)據(jù)庫(kù)在每行記錄中除了記錄我們自定義的那些字段之外,還有數(shù)據(jù)庫(kù)的隱藏的定義字段,DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID

DB_TRX_ID:最近修改事務(wù)ID,也會(huì)記錄創(chuàng)建這條記錄和最后一次修改這個(gè)記錄的事務(wù)ID

DB_ROLL_PTR:回滾指針,指向這條記錄的上一個(gè)版本,存儲(chǔ)在undo log日志中的Rollback segment回滾段中

DB_ROW_ID:這個(gè)不是一定有,如果表沒(méi)有創(chuàng)建主鍵,innodb會(huì)自動(dòng)以這列為主鍵,以這一列來(lái)創(chuàng)建B+樹(shù),產(chǎn)生一個(gè)聚簇索引,也就是創(chuàng)建的其余索引的B+樹(shù)的葉子節(jié)點(diǎn)存儲(chǔ)的是這個(gè)主鍵

實(shí)際還有一個(gè)刪除 flag 隱藏字段, 既記錄被更新或刪除并不代表真的刪除,而是刪除flag 變了

再說(shuō)undo log日志

Undo log日志分為兩種insert undo log和update undo log

Insert undo log:這種是事務(wù)在insert新數(shù)據(jù)的時(shí)候產(chǎn)生的日志,只有在事務(wù)回滾的時(shí)候需要,所以在事務(wù)commit之后可以立即丟棄該日志

Update undo log:這個(gè)是在進(jìn)行update或者delete而產(chǎn)生的日志,這個(gè)不僅是事務(wù)回滾的時(shí)候需要,在快照讀的時(shí)候也是需要的,也就是innodb的MVCC機(jī)制會(huì)用到歷史的數(shù)據(jù),所以不能隨便刪除,需要等快照讀和事務(wù)回滾都不涉及到該日志的時(shí)候,這個(gè)日志才會(huì)被相應(yīng)的線程統(tǒng)一清楚

Read View

這哥們的作用可以理解為生成的一個(gè)鏡像數(shù)據(jù),記錄當(dāng)時(shí)的情況

事務(wù)快照是用來(lái)存儲(chǔ)數(shù)據(jù)庫(kù)的事務(wù)運(yùn)行情況。一個(gè)事務(wù)快照ReadView的創(chuàng)建過(guò)程可以概括為:

m_ids:一個(gè)數(shù)值列表,用于維護(hù) Read View 生成時(shí)刻系統(tǒng)正活躍的事務(wù)ID列表

up_limit_id:是m_ids活躍事務(wù)ID中的最小的事務(wù)ID

low_limit_id:ReadView 生成時(shí)刻系統(tǒng)尚未分配的下一個(gè)事務(wù)ID ,也就是目前已出現(xiàn)過(guò)的事務(wù)ID 的最大值 + 1

可見(jiàn)性比較算法

當(dāng)事務(wù)執(zhí)行快照讀的時(shí)候,對(duì)該記錄創(chuàng)建一個(gè)Read View讀視圖,用于記錄此時(shí)的情景,把它比做條件用來(lái)判斷當(dāng)前事務(wù)可以看到哪個(gè)版本的數(shù)據(jù),到底是看到最新版本,還是看到指向undo log日志中的歷史版本呢

我們來(lái)一起看可見(jiàn)性算法,來(lái)決定該版本是否可見(jiàn)

此圖來(lái)源于知乎,侵刪

https://www.zhihu.com/question/66320138/answer/241418502

算法的流程

1. 當(dāng)行記錄的事務(wù)ID小于當(dāng)前系統(tǒng)的最小活動(dòng)id,就是可見(jiàn)的。

  1. if (trx_id < view->up_limit_id) { 
  2. return(TRUE); 

2. 當(dāng)行記錄的事務(wù)ID大于當(dāng)前系統(tǒng)的最大活動(dòng)id,就是不可見(jiàn)的。

  1. if (trx_id >= view->low_limit_id) { 
  2. return(FALSE); 

3. 當(dāng)行記錄的事務(wù)ID在活動(dòng)范圍之中時(shí),判斷是否在活動(dòng)鏈表中,如果在就不可見(jiàn),如果不在就是可見(jiàn)的。

這里我也別用那些官方語(yǔ)言給大家解釋了,我就舉個(gè)簡(jiǎn)單的例子給大家解釋

滴滴滴,跟上思路,加油,就快結(jié)束了

M_ids:一個(gè)數(shù)值列表,用于維護(hù) Read View 生成時(shí)刻系統(tǒng)正活躍的事務(wù)ID列表

up_limit_id:是m_ids活躍事務(wù)ID中的最小的事務(wù)ID

low_limit_id:ReadView 生成時(shí)刻系統(tǒng)尚未分配的下一個(gè)事務(wù)ID ,也就是目前已出現(xiàn)過(guò)的事務(wù)ID 的最大值 + 1

插入一個(gè)記錄,事務(wù)ID是10,此時(shí)版本鏈?zhǔn)?0

執(zhí)行一個(gè)update操作,事務(wù)ID是20,此時(shí)版本鏈?zhǔn)?0-10,commit

執(zhí)行一個(gè)update操作,事務(wù)ID是30,此時(shí)版本連是30-20-10,未Commit

執(zhí)行select,事務(wù)ID是40,生成一個(gè)ReadView,這是一個(gè)鏡像,此時(shí)可能已經(jīng)有更多事務(wù)操作這條數(shù)據(jù)了,活躍列表是m_ids是[30],最小事務(wù)up_limit_id也是30,最大事務(wù)low_limit_id是41

比較過(guò)程

按照這個(gè)ReadView的事務(wù)鏈30-20-10進(jìn)行上述算法的比較,30不合適,因?yàn)樵诨钴S事務(wù)中,20滿足條件,所以此時(shí)事務(wù)ID為40的讀取的就是ID為20更新的數(shù)據(jù)

事務(wù)ID30Commit,事務(wù)ID50執(zhí)行update,鏈變成了50-30-20-10,未提交

關(guān)鍵

此時(shí)事務(wù)ID為40的再次執(zhí)行了select操作,查詢了該記錄

如果事務(wù)隔離級(jí)別是已提交讀隔離級(jí)別,這時(shí)候會(huì)重新生成一個(gè)新的ReadView,那此時(shí)ReadView已經(jīng)變了,活躍列表m_ids是[50],最小事務(wù)up_limit_id也是50,最大事務(wù)low_limit_id是51

于是按照上述比較,30便符合條件了,所以此時(shí)讀出來(lái)的版本就是事務(wù)ID30的update數(shù)據(jù)了

如果事務(wù)隔離級(jí)別是可重復(fù)讀,此時(shí)不會(huì)生成新的ReadView,用的還是開(kāi)始時(shí)候生成的,所以還是20符合條件

兩種隔離級(jí)別

我們上面說(shuō)了MVCC只在READ COMMITTED 和REPEATABLE READ 兩個(gè)隔離級(jí)別下工作,已提交讀和可重復(fù)讀的區(qū)別在于他們生成ReadView的策略不同

也就是說(shuō)已提交讀隔離級(jí)別下的事務(wù)在每次查詢的開(kāi)始都會(huì)生成一個(gè)獨(dú)立的ReadView,而可重復(fù)讀隔離級(jí)別則在第一次讀的時(shí)候生成一個(gè)ReadView,之后的讀都復(fù)用之前的ReadView

我們根據(jù)名字也可以推斷,可重復(fù)讀,如果每次讀取的時(shí)候生成新的ReadView了,那符合條件的版本很可能就不一樣了,所以查出來(lái)的也就不一樣了,就不符合條件了,于是用的就是同一個(gè)ReadView

 

責(zé)任編輯:姜華 來(lái)源: Java賊船
相關(guān)推薦

2024-11-19 15:13:02

2023-12-27 18:16:39

MVCC隔離級(jí)別幻讀

2022-04-10 18:10:24

CURD鏈表

2021-04-01 08:12:20

zookeeper集群源碼

2021-12-06 08:30:49

SpringSpring Bean面試題

2021-05-20 08:54:16

Go面向對(duì)象

2020-04-16 08:22:11

HTTPS加解密協(xié)議

2010-08-23 15:06:52

發(fā)問(wèn)

2022-05-24 08:03:28

InnoDBMySQL數(shù)據(jù)

2020-12-01 11:50:49

數(shù)據(jù)庫(kù)Redis面試

2021-06-03 08:55:54

分布式事務(wù)ACID

2022-10-17 00:04:30

索引SQL訂單

2023-01-03 18:06:42

高并發(fā)架構(gòu)

2020-12-03 07:39:50

HashMap底層數(shù)據(jù)

2022-04-19 07:31:28

事務(wù)隔離機(jī)制數(shù)據(jù)庫(kù)

2021-11-24 10:10:32

axios前端攔截器

2020-08-10 07:58:18

異步編程調(diào)用

2021-09-29 19:17:51

編碼URLEncodeGBK

2022-04-01 07:52:42

JavaScript防抖節(jié)流

2021-05-08 07:53:33

面試線程池系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)