成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官問我 InnoDB 的物理存儲結(jié)構(gòu)!

數(shù)據(jù)庫 MySQL
所謂物理存儲結(jié)構(gòu),指的是 MySQL 的數(shù)據(jù)是怎么存儲在物理介質(zhì)上的,由哪些磁盤文件組成。所謂邏輯存儲結(jié)構(gòu),指的是這些數(shù)據(jù)是如何有結(jié)構(gòu)地組織起來的。

前段時間去面試,面試官突然問我:聊聊 InnoDB 的物理存儲結(jié)構(gòu)吧!

樹義突然又眼圈一黑,啥都想不起來了!

雖說之前有大致了解過 MySQL,但對 InnoDB 的物理結(jié)構(gòu),卻真的沒咋了解過!那么,今天就來聊聊 InnoDB 的物理存儲結(jié)構(gòu)吧!

相信很多人都知道邏輯結(jié)構(gòu)和物理結(jié)構(gòu)這兩個概念,但是都很好奇它們的區(qū)別是什么?

簡單地說:所謂物理存儲結(jié)構(gòu),指的是 MySQL 的數(shù)據(jù)是怎么存儲在物理介質(zhì)上的,由哪些磁盤文件組成。所謂邏輯存儲結(jié)構(gòu),指的是這些數(shù)據(jù)是如何有結(jié)構(gòu)地組織起來的。

此文所描述的 InnoDB 物理存儲結(jié)構(gòu),依據(jù)的是 MySQL 8.0 版本。

從 MySQL 官方文檔中,我們可知 InnoDB 在物理層面上可劃分為如下 7 個模塊:

  • 系統(tǒng)表空間(System Tablespace)
  • 雙寫緩存文件(Doublewrite Buffer Files)
  • Undo 表空間(Undo Tablespaces)
  • Redo Log 文件(Redo Log)
  • 獨占表空間(File-Per-Table Tablespaces)
  • 通用表空間(General Tablespaces)
  • 臨時表空間(Temporary Tablespaces)

而在這 7 個模塊中,最為關(guān)鍵的是如下三個模塊:系統(tǒng)表空間(System Tablespace)、獨立表空間(File-Per-Table Tablespaces)、日志文件組(Redo Log)。

InnoDB 磁盤存儲結(jié)構(gòu) MySQL 8.0

系統(tǒng)表空間(System Tablespace)

在開始之前,我們需要理解表空間這個概念。其實表空間,就是存儲表的空間之意。它是 InnoDB 用于描述數(shù)據(jù)存儲的術(shù)語,大致是存儲表相關(guān)數(shù)據(jù)的地方之意。系統(tǒng)表空間,顧名思義就是 InnoDB 這個系統(tǒng)的默認表空間,也叫共享表空間,對應(yīng)的是 MySQL 數(shù)據(jù)目錄下的 ibdata1 文件。如果我們將 innodb_file_per_table 設(shè)置為 off,那么我們使用 CREATE TABLE 語句創(chuàng)建的表數(shù)據(jù),都會存儲在系統(tǒng)表空間中。

而如果我們將 innodb_file_per_table 設(shè)置為 on,則每個表將獨立地產(chǎn)生一個表空間文件,以 ibd 結(jié)尾,數(shù)據(jù)、索引、表的內(nèi)部數(shù)據(jù)字典信息都將保存在這個單獨的表空間文件中。但是還有一些信息,例如 undo log 信息,還是會保存在系統(tǒng)表空間中。例如我們在 test 數(shù)據(jù)庫中創(chuàng)建了一個名為 user 的表,那么就會在 MySQL 的數(shù)據(jù)文件夾的 test 文件夾下,有一個名為 user.ibd 文件。

我們注意到系統(tǒng)表空間還有一個名為 change buffer 的東西,它到底是啥東西呢?

change buffer,其實在之前版本是插入緩沖(insert buffer),后續(xù)版本變成了 change buffer(參考:內(nèi)幕 2.4.1 章節(jié))。這一塊區(qū)域就是 Change Buffer。5.5 之前叫 Insert Buffer 插入緩沖,現(xiàn)在也能支持 delete 和 update,最后把 Change Buffer 記錄到數(shù)據(jù)頁的操作叫做 merge。

這里面有一句話很關(guān)鍵:除了主鍵聚合索引外,還產(chǎn)生了一個 name 列的輔助索引,對于該非聚集索引來說,葉子節(jié)點的插入不再有序,這時就需要離散訪問非聚集索引頁,插入性能變低。

這句話的意思是:聚集索引的插入是有序自增的,那么插入的時候直接跟在后面就可以了,不需要再做其他隨機訪問操作。而由于插入的非聚集索引列,并不是有序的,可能會插在中間,這時候就需要看看中間這個頁是否加載到內(nèi)存里。如果加載了,那還好,那就做 B+ 樹操作,調(diào)整就行。不在內(nèi)存里的話,那就麻煩了,需要讀取多次 page 到內(nèi)存。

為了提高效率,就弄了一個 insert buffer,簡單地說,就是把多次 insert 或者修改操作,先緩存起來,然后等到差不多的時候,再一起去做,提高效率,避免多次 IO 讀取。

插入緩沖,并不是緩存的一部分,而是物理頁,對于非聚集索引的插入或更新操作,不是每一次直接插入索引頁。而是先判斷插入的非聚集索引頁是否在緩沖池中。如果在,則直接插入,如果不再,則先放入一個插入緩沖區(qū)中。然后再以一定的頻率執(zhí)行插入緩沖和非聚集索引頁子節(jié)點的合并操作。

當需要更新一個數(shù)據(jù)頁時,如果數(shù)據(jù)頁在內(nèi)存中就直接更新,而如果這個數(shù)據(jù)頁還沒有在內(nèi)存中的話,在不影響數(shù)據(jù)一致性的前提下,InnoDB 會將這些更新操作緩存在 change buffer 中,這樣就不需要從磁盤中讀入這個數(shù)據(jù)頁了。在下次查詢需要訪問這個數(shù)據(jù)頁的時候,將數(shù)據(jù)頁讀入內(nèi)存,然后執(zhí)行 change buffer 中與這個頁有關(guān)的操作。

雙寫緩存文件(Doublewrite Buffer Files)

如果說插入緩沖帶給 InnoDB 存儲引擎的是性能,那么雙寫帶給 InnoDB 存儲引擎的是數(shù)據(jù)的可靠性。當數(shù)據(jù)庫宕機時,可能數(shù)據(jù)庫正在寫一個頁面,而這個頁只寫了一部分(比如 16K 的頁,只寫了前 4K 的頁),我們稱之為寫失效。在 InnoDB 存儲引擎未使用 double write 之前,曾出現(xiàn)過因為部分寫失效而導(dǎo)致數(shù)據(jù)丟失的情況。

InnoDB 存儲引擎 double write 的體系架構(gòu)如下圖所示:

雙寫緩存(double write)示意圖

double write 由兩部分組成:一部分是內(nèi)存中的 double write buffer,大小為 2MB。另一部分是物理磁盤上共享表空間中連續(xù)的 128 個頁,即兩個區(qū),大小同樣為 2MB。

當緩沖池的臟頁刷新時,并不直接寫磁盤,而是會他通過 memcpy 函數(shù)將臟頁先拷貝到內(nèi)存中的 doublewrite buffer,之后通過 doublewrite buffer 再分兩次,每次寫入 1MB 到共享表空間的物理磁盤上,然后馬上調(diào)用 fsync 函數(shù),同步磁盤,避免緩沖寫帶來的問題。在這個過程中,因為 doublewrite 頁是連續(xù)的,因此這個過程是順序?qū)懀_銷不是很大。

在完成 doublewrite 頁的寫入之后,再將 doublewrite buffer 中的頁寫入各個表空間文件中,此時的寫入則是離散的。我們可以通過 show global status like 'innodb_dblwr%'\G 觀察具體情況。

所以說雙寫,其實指的是刷臟頁的時候,即會將臟頁數(shù)據(jù)寫入共享表空間的 2 個頁中,也會寫入具體的表空間中,共享表空間的數(shù)據(jù)起到備份作用。

如果操作系統(tǒng)在將頁寫入具體的表空間過程中崩潰了,在恢復(fù)過程中,InnoDB 存儲引擎可以從共享表空間中的 doublewrite 中找到該頁的一個副本,將其拷貝到表空間文件,再應(yīng)用重做日志。

Undo 表空間(Undo Tablespaces)

undo Log 的數(shù)據(jù)默認在系統(tǒng)表空間 ibdata1 文件中,因為共享表空間不會自動收縮,也可以單獨創(chuàng)建一個 undo 表空間。

一些疑問,關(guān)于 rollback segment 與 undo log?

很多時候,我們不太懂,為啥一些說 undo log 在系統(tǒng)表空間,而官方的圖卻有 undo tablespace ?下面這段話,描述得很清楚,原因是版本變化!

Rollback Segment(rseg)稱為回滾段。Mysql5.6 之前 undo 默認記錄到系統(tǒng)表空間(ibdata),如果開啟了 innodb_file_per_table ,將放在每個表的.ibd 文件中。5.6 之后還可以創(chuàng)建獨立的 undo 表空間,8 之后更是默認打開獨立 undo 表空間,最低數(shù)量為 2,這樣才能保證至少一個 undo 表空間進行 truncate,一個 undo 表空間繼續(xù)使用。

每個 rollback Segment 中默認有 1024 個 undo log segment,mysql5.5 后 1 個 undo 表空間支持 128 個 rollback Segment。0 號 rollback Segment 默認在系統(tǒng)表空間 ibdata 中,1-32rollback Segment 在臨時表空間,33~128 在獨立 undo 表空間中(沒有打開則在系統(tǒng)表空間 ibdata 中,這樣系統(tǒng)表空間會太大),所以 1 個表空間最多支持 96*1024 個事務(wù),超了就報錯啦。

一個 undo log segment 稱為 undo log 或 undo slot 或 undo;一個 undo log 對象對應(yīng)多個 undo log record,也就是記錄的歷史版本。(Rollback segment -> 多個 Undo log segment (undo log) -> 多個 undo log record)。

疑問 2:mysql rollback segment 和 undo segment 區(qū)別

感覺這兩個應(yīng)該是差不多的呀?

結(jié)論:Rollback segment 與 undo segment 是包含的關(guān)系,每個 Rollback segment 有 1024 個 undo segment。

undo log 有兩個作用:提供回滾和多個行版本控制 (MVCC)。

在數(shù)據(jù)修改的時候,不僅記錄了 redo,還記錄了相對應(yīng)的 undo,如果因為某些原因?qū)е率聞?wù)失敗或回滾了,可以借助該 undo 進行回滾。

undo log 和 redo log 記錄物理日志不一樣,它是邏輯日志。可以認為當 delete 一條記錄時,undo log 中會記錄一條對應(yīng)的 insert 記錄,反之亦然,當 update 一條記錄時,它記錄一條對應(yīng)相反的 update 記錄。

rollback segment 稱為回滾段,每個回滾段中有 1024 個 undo log segment。

Redo Log 文件(Redo Log)

redo log 即重做日志,從字面意思來看,其表示可以將事情重做一遍的意思。而事實上,它確實是代表著這個意思。對于上文的更新語句 update t set c=c+1 where id = 2,我們的正常實現(xiàn)思路應(yīng)該是:

找到 id 為 2 的記錄,取出其 c 字段的值。

將 c 字段的值加一,之后將 id 為 2 的字段的 c 字段更新。

但實際上 MySQL 并不是這么做的,因為上述這種實現(xiàn)方式雖然能實現(xiàn),但是每次都要去讀取磁盤查找記錄、寫入磁盤更新記錄,整個過程的磁盤 IO 成本很高。為了提高效率,MySQL 使用了一種叫做 WAL(Write-Ahead Logging)的技術(shù),即寫之前先記錄變更日志(redo log),等待合適的時間再將其變更應(yīng)用到數(shù)據(jù)庫里。因為我們將操作記錄下來了,所以我們可以復(fù)現(xiàn)這個操作,這就好像我們將事情重現(xiàn)了一樣,因此叫 redo log。

使用 WAL 技術(shù),上面這條更新語句的大致實現(xiàn)思路就變成了:

記錄下更新操作日志:其要將 id 為 2 的記錄的 c 字段加 1。

某個時刻,MySQL 數(shù)據(jù)庫應(yīng)用這個 redo log 日志,將數(shù)據(jù)庫 id 為 2 的記錄的 c 字段加 1。

注意:redo log 并不會應(yīng)用于磁盤的表空間,而是在重啟時應(yīng)用于內(nèi)存表空間緩存,用于實現(xiàn) crash-safe。

可以看到,使用 WAL 技術(shù)的方式,可以不需要去讀寫磁盤,極大提高了執(zhí)行效率。

我們舉一個很形象的例子來理解 WAL 技術(shù)。想象有一個酒館,生意非常好,老板也愿意賒賬。每次別人想要賒賬,老板都得去翻賬本,看看這個人有沒有賒過賬,有賒賬的話就需要在原來的賒賬金額上再加上本次消費的金額。

在平時酒館人不多的時候,這種方式還是可以應(yīng)付應(yīng)付的。但是一旦到了酒館高峰期的時候,每個人都等著結(jié)賬,這時候再用這種方式去結(jié)賬,很可能讓客戶等太久,引起民憤。于是老板想了個辦法:我不去賬本上找誰賒賬了,我直接在黑板上記錄下誰賒賬了多少錢。例如:張三賒賬 3 塊銀元,李四賒賬 4 塊銀元。

等生意沒那么忙的時候,老板拿出賬本,將粉板上的變更記錄進賬本:哦,之前張三賒賬了 4 塊銀元,現(xiàn)在又賒賬了 3 塊銀元,所以張三現(xiàn)在總共賒賬 7 塊銀元。在這個例子中,賬本就相當于我們的 MySQL 數(shù)據(jù)庫,粉板就相當于我們的 redo log,它將消費記錄保存下來。

獨占表空間(File-Per-Table Tablespaces)

如果我們將 innodb_file_per_table 設(shè)置為 on,則每個表將獨立地產(chǎn)生一個表空間文件,以 ibd 結(jié)尾,數(shù)據(jù)、索引、表的內(nèi)部數(shù)據(jù)字典信息都將保存在這個單獨的表空間文件中。但是還有一些信息,例如 undo log 信息,還是會保存在系統(tǒng)表空間中。例如我們在 test 數(shù)據(jù)庫中創(chuàng)建了一個名為 user 的表,那么就會在 MySQL 的數(shù)據(jù)文件夾的 test 文件夾下,有一個名為 user.ibd 文件。

通用表空間(General Tablespaces)

通用表空間是后續(xù)的 MySQL 推出的表空間,其與系統(tǒng)表空間類似,可以用于存儲表的數(shù)據(jù)和索引。其作用是可以將一些業(yè)務(wù)邏輯不同的表,存放在這個通用表空間中,從而達到物理隔離的作用。

臨時表空間(Temporary Tablespaces)

存儲臨時表的數(shù)據(jù),包括用戶創(chuàng)建的臨時表,和磁盤的內(nèi)部臨時表。對應(yīng)數(shù)據(jù)目錄下的 ibtmp1 文件。當數(shù)據(jù)服務(wù)器正常關(guān)閉時,該表空間被刪除,下次重新產(chǎn)生。

參考資料:

  • MySQL :: MySQL 5.7 Reference Manual :: 14.6.3 Tablespaces
  • InnoDB 內(nèi)存結(jié)構(gòu)和磁盤結(jié)構(gòu)_wang2963973852 的博客 - CSDN 博客
  • [Mysql] 漫游 undo log | 土川的自留地
  • 詳細分析 MySQL 事務(wù)日志 (undo log) - 裸奔的小鴕鳥 - 博客園
責(zé)任編輯:武曉燕 來源: 陳樹義
相關(guān)推薦

2021-03-11 08:51:00

存儲面試位置

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫

2020-04-16 08:22:11

HTTPS加解密協(xié)議

2021-05-20 08:54:16

Go面向對象

2010-08-23 15:06:52

發(fā)問

2021-06-03 08:55:54

分布式事務(wù)ACID

2020-08-10 07:58:18

異步編程調(diào)用

2022-10-17 00:04:30

索引SQL訂單

2020-12-03 07:39:50

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

2022-04-10 18:10:24

CURD鏈表

2021-05-08 07:53:33

面試線程池系統(tǒng)

2021-05-19 08:17:35

秒殺場景高并發(fā)

2021-09-29 19:17:51

編碼URLEncodeGBK

2022-04-01 07:52:42

JavaScript防抖節(jié)流

2021-04-14 18:58:01

虛擬機 Java內(nèi)存

2021-08-28 09:06:11

Dubbo架構(gòu)服務(wù)

2020-10-26 07:07:50

線程安全框架

2022-10-08 00:08:00

apiESFacebook

2022-02-09 09:37:54

ReactorNettyI/O

2015-08-13 10:29:12

面試面試官
點贊
收藏

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

主站蜘蛛池模板: 久久久久精 | 国产中文字幕在线 | www.亚洲一区| 噜噜噜噜狠狠狠7777视频 | 免费在线性爱视频 | 国产精品久久久久久久久久久免费看 | 欧美在线观看一区 | 成人动漫一区二区 | 91久久久久久| 色视频在线免费观看 | 国产一区二区美女 | 另类视频在线 | 一区二区三区四区在线视频 | 在线国产一区二区 | 一区二区三区欧美 | 欧美一级在线 | 国产1区2区 | 国产免费人成xvideos视频 | 三级av在线 | 凹凸日日摸日日碰夜夜 | 免费观看成人av | 国产成人福利视频 | 色婷婷av99xx| 99精品欧美一区二区三区 | 男人天堂视频在线观看 | 先锋av资源网 | 成人欧美一区二区三区在线播放 | 国外成人在线视频 | 国产电影一区 | 国产精品自拍视频网站 | 中文字幕第5页 | 人人看人人射 | 麻豆91精品91久久久 | 日本在线精品视频 | 自拍视频精品 | 欧美人妇做爰xxxⅹ性高电影 | 欧美又大粗又爽又黄大片视频 | 免费观看一级视频 | 日本特黄a级高清免费大片 成年人黄色小视频 | 中文字幕成人网 | 日本精品一区二区三区在线观看 |