欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql?InnoDB?的內(nèi)存結(jié)構(gòu)詳情

 更新時間:2022年05月06日 11:45:04   作者:??斜月????  
這篇文章主要介紹了Mysql InnoDB的內(nèi)存結(jié)構(gòu)詳情,InnoDB存儲引擎的邏輯存儲結(jié)構(gòu)是什么呢,下面我們就一起進(jìn)入文章了解更多詳細(xì)內(nèi)容吧,感興趣的小伙伴可以參考一下

1 前言

我們都熟悉mysql數(shù)據(jù)庫服務(wù)架構(gòu),也清楚 sql 的執(zhí)行順序,mysql的數(shù)據(jù)在磁盤和內(nèi)存中的存儲結(jié)構(gòu)是采用B+樹的數(shù)據(jù)結(jié)構(gòu),但是在InnoDB引擎中,數(shù)據(jù)在內(nèi)存和磁盤中的展示形式以及怎么和mysql的服務(wù)架構(gòu)建立聯(lián)系,sql 查詢和 InnoDB 引擎之前的聯(lián)系,可能就不是不清楚了。

mysql 的邏輯架構(gòu)圖如下所示: 

2 InnoDB 存儲引擎結(jié)構(gòu)

InnoDB存儲引擎的邏輯存儲結(jié)構(gòu)是什么呢,其實所有的數(shù)據(jù)都被邏輯地放在了一個空間中這個空間中的文件就是實際存在的物理文件,即表空間。默認(rèn)情況下,一個數(shù)據(jù)庫表占用一個表空間,表空間中存放該表對應(yīng)的數(shù)據(jù)、索引、insert buffer bitmap undo信息、insert buffer 索引頁、double write buffer 等是放在共享表空間中的。

# 默認(rèn)一個數(shù)據(jù)庫表單獨占有一個表空間
show variables like '%innodb_file_per_table%'
innodb_file_per_table=ON
# 修改設(shè)置
SET GLOBAL innodb_file_per_table=OFF; 

2.1 InnoDB表存儲引擎文件

 每個表空間由 段 segment 區(qū) extent 頁 page 組成。頁是數(shù)據(jù)存儲數(shù)據(jù)的基本單位,默認(rèn)大小為 16kb。 區(qū)是由連續(xù)頁組成的空間,默認(rèn)大小為 1MB。多個區(qū)構(gòu)成表的段。 InnoDB 邏輯存儲結(jié)構(gòu) 

在我們執(zhí)行sql時,不論是查詢還是修改,myql 總會把數(shù)據(jù)從磁盤讀取內(nèi)內(nèi)存中,而且在讀取數(shù)據(jù)時,不會單獨加在一條數(shù)據(jù),而是直接加載數(shù)據(jù)所在的數(shù)據(jù)頁到內(nèi)存中,而讀取的方式有兩種,現(xiàn)行預(yù)讀方式和隨機(jī)預(yù)讀方式,默認(rèn)采用線性預(yù)讀方式。

InnoDB 引擎架構(gòu) :

2.2 InnoDB 預(yù)讀機(jī)制

線性預(yù)讀和隨機(jī)預(yù)讀:

線性預(yù)讀是以 extent 為單位,而隨機(jī)預(yù)讀是以 extent 中的page 為單位,線性預(yù)讀著眼于將下一個extent 數(shù)據(jù)讀取到 buffer pool 中,而隨機(jī)預(yù)讀是將當(dāng)前extent中剩余的page讀到 buffer pool 中。 如果一個extent 區(qū)中被順序讀取得page數(shù)量超過一定的數(shù)量( innodb_read_ahead_threshold),則直接加載 extent 中剩余的數(shù)據(jù)頁。

2.3 InnoDB 特性

2.3.1 插入緩存

插入緩沖(Insert Buffer/Change Buffer)為了提升插入性能,insert buffer 是 insert buffer 的增強(qiáng)版,insert buffer 只對插入有效,而change buffer對 insert/update/delete 都有效。插入緩存只對非唯一索引和輔助索引有效,對每一次的插入不是寫到索引頁中,而是先判斷插入的非聚集索引頁是否在緩存中,如果在則直接插入,不存在則插入到 insert buffer 中,按照一定的頻率進(jìn)行合并操作,寫回到磁盤。這樣將多個插入操作合并進(jìn)一個操作中,目的是為了減少隨機(jī)IO帶來的性能損耗。

2.3.2 二次寫 (double write)

插入緩存給 InnoDB 存儲引擎帶來了性能上的提升,而 double write 則是保障 InnoDB 存儲引擎操作數(shù)據(jù)頁的可靠性。double write 分為兩部分組成,一部分在內(nèi)存中的 double write buffer, 大小為 2MB,另一部分是物理磁盤上共享表空間中連續(xù)的128個數(shù)據(jù)頁,即2個區(qū)大小(同樣是2MB)。在對緩沖池的臟頁進(jìn)行刷新時,并不是直接寫磁盤,而是通過 memcpy 函數(shù)將臟頁復(fù)制到內(nèi)存中的 doublewrite buffer,之后通過doublewrite buffer 在分兩次,每次1MB 順序地寫入共享表空間的物理磁盤上,然后馬上調(diào)用 fsync 將數(shù)據(jù)同步至磁盤。由于doublewrite 是連續(xù)的空間,這樣的順序?qū)慖O開銷不大。在doublewrite頁寫完后,再次離散寫入各個表空間。如果操作系統(tǒng)在將數(shù)據(jù)頁寫入磁盤發(fā)生崩潰,那么在恢復(fù)的過程中,InnoDB 引擎會從共享表空間中的doublewrite找到該頁的一個副本,將其復(fù)制到表空間文件,再應(yīng)用重做日志。

2.3.3 自適應(yīng)hash索引

hash是一種等值查詢,InnoDB 存儲引擎會監(jiān)控對表上各個索引頁的查詢,如果觀察到建立hash索引會帶來速度提升,則建立相應(yīng)的索引,因此稱為自適應(yīng)哈希索引(Adaptive Hash Index,AHI)。AHI是通過緩沖池中的B+樹頁構(gòu)造而來,建立速度比較快,而且不需要對整張表建立哈希索引,只是建立熱點頁的索引。AHI默認(rèn)是開啟的狀態(tài)。

2.3.4 異步IO

為了提高磁盤的操作性能, 當(dāng)前的數(shù)據(jù)庫系統(tǒng)一般采用異步IO(Asynchronous IO,AIO)的方式來處理磁盤操作,InnoDB 存儲引擎也是如此,AIO的優(yōu)勢在于減少SQL查詢需要的時間,另外也可以進(jìn)行IO Merge 操作,就是將多個IO合并為1個IO,這樣就可以提高IOPS的性能。

# 開啟本地 AIO
show valiables like 'innodb_use_native_aio';

2.3.5 刷新鄰接頁

InnoDB 存儲引擎提供了 Flush Neighbor Page(刷新鄰接頁)的特性,當(dāng)刷新一個臟頁時,InnoDB 存儲引擎會檢測該區(qū)內(nèi)是否存在其它臟頁,如果存在,則一并進(jìn)行刷新,這樣做得好處顯而易見,可以將多個操作合并成一個操作,對于機(jī)械硬盤有著明顯的優(yōu)勢,但對于固定硬盤,本事就有較高的IOPS,是否開啟需要根據(jù)情況而定,

參數(shù)設(shè)置如下:

show varables like 'innodb_flush_neighbors'

3 sql 執(zhí)行的邏輯

3.1 sql 執(zhí)行

mysql寫文件有2塊緩存。一塊是自己定義在內(nèi)存的log buffer, 另一個是磁盤映射到內(nèi)存的os cache。 mysql可以 調(diào)用 flush 主動將log buffer 刷新到磁盤內(nèi)存映射,也可以調(diào)用 fsync 強(qiáng)制操作系同步磁盤映射文件到磁盤。默認(rèn)情況下innodb_flush_log_at_trx_commit和sync_binlog 配置都為1。

不僅InnoDB引擎中有 buffer 的概念,這個是在用戶空間中,而且在內(nèi)核空間中也有 OS buffer的概念 

 還可以同時調(diào)用 flush + fsync, 將緩存直接落盤。
innodb_flush_log_at_trx_commit = 0就是每秒調(diào)用 flush + fsync ,定時器自己維護(hù)。
innodb_flush_log_at_trx_commit = 1就是實時調(diào)用 flush + fsync 沒法批處理,性能很低。
innodb_flush_log_at_trx_commit = 2就是實時flush ,定時 fsync 交給OS維護(hù)定時器。
sync_binlog 配置
等于0:表示每次提交事務(wù)只write不fsync
等于1:表示每次提交事務(wù)都執(zhí)行fsync
等于n:表示事務(wù)在write后,會累積N個事務(wù)后才fsync。

show variables like 'sync_binlog';
show variables like 'innodb_flush_log_at_trx_commit';
# 查看 mysql 正在執(zhí)行的進(jìn)程 
show processlist

InnoDB引擎BufferPool、LogBuffer、OS Buffer、Log files 之間的關(guān)系。 

mysql 在執(zhí)行增刪改sql時,InnoDB 引擎的執(zhí)行步驟如下:

  • 1 執(zhí)行器拿到需要執(zhí)行的sql,需要根據(jù)更新條件從磁盤中加載需要修改的數(shù)據(jù)到內(nèi)存中,也就是存放在 buffer pool 中。
  • 2 在修改對應(yīng)的數(shù)據(jù)之前,需要將其數(shù)據(jù)進(jìn)行備份,也就是將數(shù)據(jù)放進(jìn) undo log 中,方便在事務(wù)回滾時進(jìn)行操作。
  • 3 直接在內(nèi)存中按照sql語句修改對應(yīng)的值。
  • 4 修改完后將按照修改后的數(shù)據(jù)寫 redo log buffer。
  • 5 將 redo log 的內(nèi)容進(jìn)行寫盤操作,這一步的操作參見 innodb_flush_at_trx_commit 的配置,一般是先寫入系統(tǒng)的緩存中,然后由操作系統(tǒng)DMA異步操作寫入系統(tǒng)文件中。 flush 操作只是把系統(tǒng)內(nèi)存中的數(shù)據(jù)寫入操作系統(tǒng)的緩沖中,數(shù)據(jù)讀寫一般是由內(nèi)核線程完成的,這一步是數(shù)據(jù)從用戶線程轉(zhuǎn)變成內(nèi)核線程進(jìn)行操作,在讀寫文件時,在磁盤文件和內(nèi)存之間會有多級緩存,用于提高數(shù)據(jù)交換效率,這里的 os cache 起到的就是這個作用。
  • 6 在寫完redo log 后,然后進(jìn)行 bin log 寫入操作。
  • 7 和 redo log 的操作類似,也是先寫入 os cache 再有操作系統(tǒng)刷到磁盤文件中。sync_log 的配置如圖所示。一般情況下,數(shù)據(jù)庫innodb_flush_at_trx_commit 和 sync_log 配置都為 1。
  • 8 在 redo log 和 bin log 寫完后,就可以進(jìn)行事務(wù)提交。在數(shù)據(jù)進(jìn)行寫盤操作時, InnoDB 采用兩次寫的方式進(jìn)行寫數(shù)據(jù)。

先寫redo log 再寫 bin log的原因: 由于mysql 是通過 bin log 進(jìn)行復(fù)制傳輸?shù)?,如果先提交?redo log,還沒有寫bin log時出現(xiàn)了宕機(jī),mysql 實例恢復(fù)時根據(jù) redo log進(jìn)行恢復(fù),就會造成 從庫和主庫之間的數(shù)據(jù)不一致。

二進(jìn)制日志文件的記錄格式為 statement、row 和 mixed,statement 模式就是直接執(zhí)行sql,如果其中有函數(shù)操作(比如數(shù)據(jù)庫時間設(shè)置為 now() )那就會造成數(shù)據(jù)不準(zhǔn)確。row 模式就是同步所有行的數(shù)據(jù),如果全表操作修改狀態(tài),那這種模式就不合適了,因此在數(shù)據(jù)同步時需要根據(jù)情況采用 mixed 的混合模式。

3.2 FreeList、LRU List 和 Flush List

Free List 空閑列表:

記錄所有未被占用的數(shù)據(jù)頁,按照順序?qū)⒓虞d到內(nèi)存的數(shù)據(jù)放入buffer pool 中,并刪除對應(yīng) Free List 中的節(jié)點

LRU List LRU 數(shù)據(jù)訪問列表:

將冷熱數(shù)據(jù)塊連接起來,根據(jù) LRU 算法進(jìn)行維護(hù)。如果加載進(jìn)內(nèi)存的數(shù)據(jù)一次性放入列表頭部,再不確定這批數(shù)據(jù)的熱度情況下,會造成一部分?jǐn)?shù)據(jù)的淘汰,mysql InnoDB 的做法是將數(shù)據(jù)放置在靠后的位置,如果數(shù)據(jù)在1s內(nèi)被訪問了,才能進(jìn)入鏈表頭部,即數(shù)據(jù)熱區(qū)。

# 將新加載的數(shù)據(jù)放置在鏈表的位置 默認(rèn)為 37 即5/8處,
show variables like 'innodb_old_blocks_pct';
# 冷區(qū)數(shù)據(jù)間隔多久訪問才放入鏈表的熱端,默認(rèn)為1000ms
show variables like 'innodb_old_blocks_time';

Flush List 刷新臟頁列表:

記錄內(nèi)存中修改的數(shù)據(jù)頁,使用雙向鏈表進(jìn)行連接,在方便的時候做落盤操作。

InnoDB 中的 redo log 大小是固定的,在MYSQL數(shù)據(jù)庫Innodb 引擎mvcc鎖實現(xiàn)原理 中提到過 redo log 是保證事務(wù)持久性的,其文件個數(shù)也是可以根據(jù)需要進(jìn)行配置,通過循環(huán)寫文件的方式來實現(xiàn)的,當(dāng) write pos 追趕上 checkpoint 后,這個時候就不能再繼續(xù)執(zhí)行新的命令,需要把check point 往前推進(jìn),也就是把redo log 里的內(nèi)容持久化,騰出空間繼續(xù)寫日志。

數(shù)據(jù)操作:

redo log buffer 循環(huán)寫入 :

這里先寫日志再寫磁盤的關(guān)鍵點也是一個技術(shù),Write-Ahead Logging(WAL技術(shù))。

關(guān)于 redo log 的配置可以參見如下命令執(zhí)行查看。

show?variables?like?'%innodb_log%'
------- 執(zhí)行結(jié)果 ------
innodb_log_buffer_size	16777216
innodb_log_checksums	ON
innodb_log_compressed_pages	ON
innodb_log_file_size	50331648
innodb_log_files_in_group	2
innodb_log_group_home_dir	./
innodb_log_write_ahead_size	8192
innodb_log_buffer_size 為內(nèi)存中 redo log buffer 的大小,16777216/1024/1024=16MB
innodb_log_file_size 為每個redo log 的大小,50331648/1024/1024=48MB
innodb_log_files_in_group 為 redo log 文件組中文件的個數(shù),默認(rèn)為2個 
查看數(shù)據(jù)庫表狀態(tài)
show table status like 'my_table';

到此這篇關(guān)于Mysql InnoDB 的內(nèi)存結(jié)構(gòu)詳情的文章就介紹到這了,更多相關(guān)Mysql InnoDB 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL基本運維命令詳解

    MySQL基本運維命令詳解

    這篇文章主要介紹了MySQL基本運維命令,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • MySQL刪除表時I/O錯誤的原因分析與解決

    MySQL刪除表時I/O錯誤的原因分析與解決

    這篇文章主要給大家介紹了關(guān)于MySQL刪除表時I/O錯誤的原因分析與解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • windows server 2008 64位MySQL5.6免安裝版本配置方法圖解

    windows server 2008 64位MySQL5.6免安裝版本配置方法圖解

    這篇文章主要介紹了windows server 2008 64位MySQL5.6免安裝版本配置方法圖解,需要的朋友可以參考下
    2017-08-08
  • Mysql索引類型與基本用法實例分析

    Mysql索引類型與基本用法實例分析

    這篇文章主要介紹了Mysql索引類型與基本用法,結(jié)合實例形式分析了Mysql索引類型中普通索引、唯一索引、主鍵索引、組合索引、全文索引基本概念、原理與使用方法,需要的朋友可以參考下
    2020-06-06
  • Mysql日期查詢的詳細(xì)介紹

    Mysql日期查詢的詳細(xì)介紹

    這篇文章主要介紹了Mysql日期查詢的詳細(xì)介紹,根據(jù)時間段進(jìn)行查詢數(shù)據(jù)庫中單表中的數(shù)據(jù),如果感興趣的來了解一下
    2020-07-07
  • mysql 5.6.14主從復(fù)制(也稱mysql AB復(fù)制)環(huán)境配置方法

    mysql 5.6.14主從復(fù)制(也稱mysql AB復(fù)制)環(huán)境配置方法

    這篇文章主要介紹了mysql 5.6.14主從復(fù)制(也稱mysql AB復(fù)制)環(huán)境配置方法,需要的朋友可以參考下
    2016-04-04
  • mysql中null(IFNULL,COALESCE和NULLIF)相關(guān)知識點總結(jié)

    mysql中null(IFNULL,COALESCE和NULLIF)相關(guān)知識點總結(jié)

    這篇文章主要介紹了mysql中null(IFNULL,COALESCE和NULLIF)相關(guān)知識點,結(jié)合實例形式總結(jié)分析了mysql中關(guān)于null的判斷、使用相關(guān)操作技巧與注意事項,需要的朋友可以參考下
    2019-12-12
  • mysql中四種備份模式

    mysql中四種備份模式

    本文主要介紹了mysql中四種備份模式,無論使用哪種備份方式,都需要根據(jù)業(yè)務(wù)需求和數(shù)據(jù)量大小來選擇合適的備份策略,并定期驗證備份是否有效,感興趣的可以了解一下
    2023-11-11
  • MySQL數(shù)據(jù)庫優(yōu)化經(jīng)驗詳談(服務(wù)器普通配置)

    MySQL數(shù)據(jù)庫優(yōu)化經(jīng)驗詳談(服務(wù)器普通配置)

    同時在線訪問量繼續(xù)增大 對于1G內(nèi)存的服務(wù)器明顯感覺到吃力嚴(yán)重時甚至每天都會死機(jī) 或者時不時的服務(wù)器卡一下 這個問題曾經(jīng)困擾了我半個多月MySQL使用是很具伸縮性的算法,因此你通常能用很少的內(nèi)存運行或給MySQL更多的被存以得到更好的性能。
    2011-03-03
  • mysql日期date型和int型互換的方法

    mysql日期date型和int型互換的方法

    下面小編就為大家?guī)硪黄猰ysql日期date型和int型互換的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10

最新評論