最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

1 前言

我們都熟悉mysql數(shù)據(jù)庫(kù)服務(wù)架構(gòu),也清楚 sql 的執(zhí)行順序,mysql的數(shù)據(jù)在磁盤和內(nèi)存中的存儲(chǔ)結(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 存儲(chǔ)引擎結(jié)構(gòu)

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

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

2.1 InnoDB表存儲(chǔ)引擎文件

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

在我們執(zhí)行sql時(shí),不論是查詢還是修改,myql 總會(huì)把數(shù)據(jù)從磁盤讀取內(nèi)內(nèi)存中,而且在讀取數(shù)據(jù)時(shí),不會(huì)單獨(dú)加在一條數(shù)據(jù),而是直接加載數(shù)據(jù)所在的數(shù)據(jù)頁(yè)到內(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ù)讀著眼于將下一個(gè)extent 數(shù)據(jù)讀取到 buffer pool 中,而隨機(jī)預(yù)讀是將當(dāng)前extent中剩余的page讀到 buffer pool 中。 如果一個(gè)extent 區(qū)中被順序讀取得page數(shù)量超過(guò)一定的數(shù)量( innodb_read_ahead_threshold),則直接加載 extent 中剩余的數(shù)據(jù)頁(yè)。

2.3 InnoDB 特性

2.3.1 插入緩存

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

2.3.2 二次寫 (double write)

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

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

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

2.3.4 異步IO

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

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

2.3.5 刷新鄰接頁(yè)

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

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

show varables like 'innodb_flush_neighbors'

3 sql 執(zhí)行的邏輯

3.1 sql 執(zhí)行

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

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

 還可以同時(shí)調(diào)用 flush + fsync, 將緩存直接落盤。
innodb_flush_log_at_trx_commit = 0就是每秒調(diào)用 flush + fsync ,定時(shí)器自己維護(hù)。
innodb_flush_log_at_trx_commit = 1就是實(shí)時(shí)調(diào)用 flush + fsync 沒法批處理,性能很低。
innodb_flush_log_at_trx_commit = 2就是實(shí)時(shí)flush ,定時(shí) fsync 交給OS維護(hù)定時(shí)器。
sync_binlog 配置
等于0:表示每次提交事務(wù)只write不fsync
等于1:表示每次提交事務(wù)都執(zhí)行fsync
等于n:表示事務(wù)在write后,會(huì)累積N個(gè)事務(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時(shí),InnoDB 引擎的執(zhí)行步驟如下:

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

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

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

3.2 FreeList、LRU List 和 Flush List

Free List 空閑列表:

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

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

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

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

Flush List 刷新臟頁(yè)列表:

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

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

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

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

這里先寫日志再寫磁盤的關(guān)鍵點(diǎn)也是一個(gè)技術(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 為每個(gè)redo log 的大小,50331648/1024/1024=48MB
innodb_log_files_in_group 為 redo log 文件組中文件的個(gè)數(shù),默認(rèn)為2個(gè) 
查看數(shù)據(jù)庫(kù)表狀態(tài)
show table status like 'my_table';

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

相關(guān)文章

  • MySQL無(wú)法輸入中文字符問(wèn)題的解決辦法

    MySQL無(wú)法輸入中文字符問(wèn)題的解決辦法

    MySQL無(wú)法輸入中文的問(wèn)題大多是由于字符集不匹配所導(dǎo)致的,下面這篇文章主要給大家介紹了關(guān)于MySQL無(wú)法輸入中文字符問(wèn)題的解決辦法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • MySql索引使用策略分析

    MySql索引使用策略分析

    這篇文章主要介紹了MySql索引使用策略分析,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2020-11-11
  • 深入理解MySQL數(shù)據(jù)類型的選擇優(yōu)化

    深入理解MySQL數(shù)據(jù)類型的選擇優(yōu)化

    這篇文章主要介紹了深入理解MySQL數(shù)據(jù)類型的選擇優(yōu)化,MySQL數(shù)據(jù)類型是定義列中可以存儲(chǔ)什么數(shù)據(jù)以及該數(shù)據(jù)實(shí)際怎樣存儲(chǔ)的基本規(guī)則,正確的選擇數(shù)據(jù)庫(kù)字段的字段類型對(duì)于數(shù)據(jù)庫(kù)性能有很大的影響
    2022-08-08
  • MySQL無(wú)法啟動(dòng)、無(wú)法停止解決方法(安全設(shè)置后容易出現(xiàn))

    MySQL無(wú)法啟動(dòng)、無(wú)法停止解決方法(安全設(shè)置后容易出現(xiàn))

    最近在Win2003上的MySQL出現(xiàn)過(guò)多次正常運(yùn)行時(shí)無(wú)法連接數(shù)據(jù)庫(kù)故障,根本原因就是因?yàn)榘踩O(shè)置以后容易出現(xiàn)的問(wèn)題,其實(shí)很簡(jiǎn)單的解決
    2012-03-03
  • sysbench的安裝與使用 分享

    sysbench的安裝與使用 分享

    sysbench是一款開源的多線程性能測(cè)試工具,可以執(zhí)行CPU/內(nèi)存/線程/IO/數(shù)據(jù)庫(kù)等方面的性能測(cè)試。數(shù)據(jù)庫(kù)目前支持MySQL/Oracle/PostgreSQL
    2013-09-09
  • mysql中GROUP_CONCAT的使用方法實(shí)例分析

    mysql中GROUP_CONCAT的使用方法實(shí)例分析

    這篇文章主要介紹了mysql中GROUP_CONCAT的使用方法,結(jié)合實(shí)例形式分析了MySQL中GROUP_CONCAT合并查詢結(jié)果的相關(guān)操作技巧,需要的朋友可以參考下
    2020-02-02
  • 磁盤寫滿導(dǎo)致MySQL復(fù)制失敗的解決方案

    磁盤寫滿導(dǎo)致MySQL復(fù)制失敗的解決方案

    這篇文章主要介紹了磁盤寫滿導(dǎo)致MySQL復(fù)制失敗的解決方案,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下
    2021-04-04
  • 一文弄懂MySQL中redo?log與binlog的區(qū)別

    一文弄懂MySQL中redo?log與binlog的區(qū)別

    在學(xué)習(xí)mysql數(shù)據(jù)庫(kù)時(shí),不可避免要去接觸到redo log和binlog,好多人對(duì)這兩者的概念分不太清,下面這篇文章主要給大家介紹了關(guān)于MySQL中redo?log與binlog區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • mysql多行子查詢實(shí)戰(zhàn)案例(只包含不相關(guān)子查詢)

    mysql多行子查詢實(shí)戰(zhàn)案例(只包含不相關(guān)子查詢)

    在MySQL中多行子查詢(也稱為 IN 子查詢)是指子查詢返回多行數(shù)據(jù),并且這些數(shù)據(jù)用于主查詢中的某個(gè)條件判斷,這篇文章主要介紹了mysql多行子查詢(只包含不相關(guān)子查詢)的相關(guān)資料,需要的朋友可以參考下
    2024-10-10
  • JDBC連接MySQL出現(xiàn)的問(wèn)題

    JDBC連接MySQL出現(xiàn)的問(wèn)題

    采用JDBC連接MySQL數(shù)據(jù)庫(kù),JDBC驅(qū)動(dòng)已經(jīng)添加到eclipse的項(xiàng)目構(gòu)建路徑里了,按理來(lái)說(shuō)應(yīng)該一切正常。運(yùn)行項(xiàng)目后提示“無(wú)法加載驅(qū)動(dòng)”。
    2010-12-12

最新評(píng)論

宿松县| 墨玉县| 龙井市| 绥中县| 离岛区| 炉霍县| 昌吉市| 德州市| 隆尧县| 监利县| 永泰县| 德庆县| 大姚县| 漳州市| 寿阳县| 孝义市| 城步| 洛扎县| 泗阳县| 搜索| 辛集市| 巧家县| 宜宾市| 富平县| 江永县| 保定市| 噶尔县| 从化市| 安新县| 临猗县| 泸定县| 通道| 吴堡县| 寿光市| 玉门市| 黄山市| 榆中县| 秦皇岛市| 绥宁县| 昌吉市| 夹江县|