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

MySQL InnoDB存儲(chǔ)引擎的深入探秘

 更新時(shí)間:2019年02月20日 14:32:29   作者:Dreamans  
這篇文章主要給大家介紹了關(guān)于MySQL InnoDB存儲(chǔ)引擎的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在MySQL中InnoDB屬于存儲(chǔ)引擎層,并以插件的形式集成在數(shù)據(jù)庫中。從MySQL5.5.8開始,InnoDB成為其默認(rèn)的存儲(chǔ)引擎。InnoDB存儲(chǔ)引擎支持事務(wù)、其設(shè)計(jì)目標(biāo)主要是面向OLTP的應(yīng)用,主要特點(diǎn)有:支持事務(wù)、行鎖設(shè)計(jì)支持高并發(fā)、外鍵支持、自動(dòng)崩潰恢復(fù)、聚簇索引的方式組織表結(jié)構(gòu)等。

體系架構(gòu)

InnoDB存儲(chǔ)引擎是由內(nèi)存池、后臺(tái)線程、磁盤存儲(chǔ)三大部分組成。

線程

InnoDB 使用的是多線程模型, 其后臺(tái)有多個(gè)不同的線程負(fù)責(zé)處理不同的任務(wù)

Master Thread

Master Thread是最核心的一個(gè)后臺(tái)線程,主要負(fù)責(zé)將緩沖池中的數(shù)據(jù)異步刷新到磁盤,保證數(shù)據(jù)的一致性。包括臟頁刷新、合并插入緩沖、UNDO頁的回收等。

IO Thread

在 InnoDB 存儲(chǔ)引擎中大量使用了異步IO(Async IO)來處理寫IO請求, IO Thread的工作主要是負(fù)責(zé)這些 IO 請求的回調(diào)。

Purge Thread

事務(wù)提交后,其所使用的undo log可能不再需要,因此需要Purge Thread來回收已經(jīng)分配并使用的UNDO頁。InnoDB支持多個(gè)Purge Thread, 這樣做可以加快UNDO頁的回收,提高CPU的使用率以及提升存儲(chǔ)引擎的性能。

Page Cleaner Thread

Page Cleaner Thread的作用是取代Master Thread中臟頁刷新的操作,其目的是減輕原Master Thread的工作及對于用戶查詢線程的阻塞,進(jìn)一步提高InnoDB存儲(chǔ)引擎的性能。

內(nèi)存

InnoDB 存儲(chǔ)引擎內(nèi)存的結(jié)構(gòu)

緩沖池

InnoDB存儲(chǔ)引擎是基于磁盤存儲(chǔ)的,并將其中的記錄按照頁的方式進(jìn)行管理。但是由于CPU速度和磁盤速度之間的鴻溝,基于磁盤的數(shù)據(jù)庫系統(tǒng)通常使用緩沖池記錄來提高數(shù)據(jù)庫的的整體性能。

緩沖池其實(shí)就是通過內(nèi)存的速度來彌補(bǔ)磁盤速度較慢對數(shù)據(jù)庫性能的影響。在數(shù)據(jù)庫進(jìn)行讀取操作時(shí),首先將磁盤中的頁放入緩沖池中,下次再讀取相同頁時(shí),首先從緩沖池中獲取該頁數(shù)據(jù),起到高速緩存的作用。

數(shù)據(jù)的修改操作,則首先修改在緩沖池中的頁數(shù)據(jù),然后使用一種稱為Checkpoint的機(jī)制刷新到磁盤上。

緩沖池的大小直接影響數(shù)據(jù)庫的整體性能,對于InnoDB存儲(chǔ)引擎而言,緩沖池配置通過參數(shù) innodb_buffer_pool_size 來設(shè)置。使用 SHOW VARIABLES LIKE 'innodb_buffer_pool_size' 命令可查看緩沖池配置:

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size' \G
*************************** 1. row ***************************
Variable_name: innodb_buffer_pool_size
 Value: 134217728
1 row in set (0.01 sec)

緩沖池中緩存的數(shù)據(jù)頁類型有: 索引頁、undo頁、插入緩沖、自適應(yīng)哈希索引、InnoDB鎖信息、數(shù)據(jù)字典信息等,索引頁和數(shù)據(jù)頁占緩沖池很大的一部分。

重做日志緩沖

緩沖池中的頁數(shù)據(jù)比磁盤要新時(shí),需要將新數(shù)據(jù)刷新到磁盤中。InnoDB采用Write Ahead Log策略來刷新數(shù)據(jù),即當(dāng)事務(wù)提交時(shí),先寫入重做日志緩沖,重做日志緩沖會(huì)按一定頻率刷新到重置日志文件中,然后臟頁會(huì)根據(jù)checkpoint機(jī)制刷新到磁盤。

重做日志緩沖不需要設(shè)置很大,通常情況下8M能滿足大部分的應(yīng)用場景。重做日志支持一下三種情況觸發(fā)刷新:

  • Master Thread每一秒將重做日志緩沖刷新到重做日志文件
  • 每次事務(wù)提交時(shí)將重做日志緩沖刷新到重做日志文件
  • 當(dāng)重做日志緩沖池剩余空間小于1/2時(shí),重做日志緩沖刷新到重做日志文件


額外內(nèi)存池

在InnoDB存儲(chǔ)引擎中,對內(nèi)存的管理是通過一種稱為內(nèi)存堆的方式進(jìn)行的。在對一些數(shù)據(jù)結(jié)構(gòu)本身的內(nèi)存進(jìn)行分配時(shí),需要從額外的內(nèi)存池中進(jìn)行申請,當(dāng)該區(qū)域的內(nèi)存不夠時(shí),會(huì)從緩沖池中進(jìn)行申請。


InnoDB支持的鎖有:

  • 共享鎖和排它鎖
  • 意向鎖
  • 記錄鎖
  • 間隙鎖
  • 自增鎖

共享鎖和排他鎖

InnoDB引擎實(shí)現(xiàn)了兩種標(biāo)準(zhǔn)的行級鎖,共享鎖(shared (S) locks) 和排他鎖 (exclusive (X) locks)。共享鎖允許一個(gè)占有鎖的事務(wù)去讀取一行數(shù)據(jù),排它鎖則允許事務(wù)對某一行記錄進(jìn)行寫操作。

如果一個(gè)事務(wù)持有了一個(gè)共享鎖,其他事務(wù)仍然可以獲取這行記錄的共享鎖,但不能獲取到這行記錄的排它鎖。當(dāng)一個(gè)事務(wù)獲取到了某一行的排它鎖,則其他事務(wù)將無法再獲取這行記錄的共享鎖和排它鎖。

意向鎖

在InnoDB中,意向鎖是一種表級鎖,分為共享鎖和排他鎖:

  • 意向共享鎖:將要去獲取某一行的共享鎖
  • 意向排它鎖:將要去獲取某一行的排它鎖

事務(wù)在獲取共享/排它鎖之前必須先獲取意向共享/排它鎖,意向鎖不會(huì)阻塞其他任何對表的操作,他只是告訴其他事務(wù)他將要去獲取某一行的共享鎖或者排他鎖。

記錄鎖

記錄是是作用在索引上的一種鎖,他鎖住的是某一條記錄的索引而非記錄本身,如果當(dāng)前表沒有索引那么InnoDB將會(huì)為其創(chuàng)建一個(gè)隱藏的聚集索引,而Record Locks將會(huì)鎖住這個(gè)隱藏的聚集索引。

間隙鎖

間隙鎖和記錄鎖一樣也是作用在索引上,不同的是記錄鎖只作用于一條索引記錄而間隙鎖可以鎖住一個(gè)范圍內(nèi)的索引。間隙鎖在InnoDB的唯一作用就是防止其他事務(wù)的插入操作,以此防止幻讀的發(fā)生。

自增鎖

自增鎖是一種特殊的表級鎖,他只作用在包含自增列的插入操作時(shí)。當(dāng)一個(gè)事務(wù)正在插入一條數(shù)據(jù)時(shí),其他的任何事務(wù)都必須等待整個(gè)事務(wù)完成插入操作,在取獲取鎖來執(zhí)行插入操作。

事務(wù)

ACID

事務(wù)是數(shù)據(jù)庫作為OLTP最為重要的特性,說起事務(wù)不得不提起ACID四個(gè)基本特性:

  • 原子性(Atomicity) :事務(wù)最小工作單元,要么全成功,要么全失敗
  • 一致性(Consistency): 事務(wù)開始和結(jié)束后,數(shù)據(jù)庫的完整性不會(huì)被破壞
  • 隔離性(Isolation) :不同事務(wù)之間互不影響,四種隔離級別為RU(讀未提交)、RC(讀已提交)、RR(可重復(fù)讀)、SERIALIZABLE (串行化)
  • 持久性(Durability) :事務(wù)提交后,對數(shù)據(jù)的修改是永久性的,即使系統(tǒng)故障也不會(huì)丟失

InnoDB的原子性、持久性和一致性主要是通過Redo Log、Undo Log和Force Log at Commit機(jī)制機(jī)制來完成的。Redo Log用于在崩潰時(shí)恢復(fù)數(shù)據(jù),Undo Log用于對事務(wù)的影響進(jìn)行撤銷,也可以用于多版本控制。而Force Log at Commit機(jī)制保證事務(wù)提交后Redo Log日志都已經(jīng)持久化。隔離性則是由鎖和MVCC來保證的。

隔離級別

在MySQL中,事務(wù)有4種隔離級別,分別是:

  • Read Uncommitted 未提交讀
  • Read Committed 已提交讀
  • Repeatable Read 可重復(fù)讀
  • Serializable 可串行化

在理解四種隔離級別之前,我們需要先了解另外三個(gè)名詞:

  • 臟讀

    a事務(wù)會(huì)讀取到b事務(wù)還未提交的數(shù)據(jù),但是b事務(wù)由于某種原因進(jìn)行回滾操作,這樣,a事務(wù)讀取的數(shù)據(jù)是不可用的,進(jìn)而會(huì)造成一些異常結(jié)果。

  • 不可重復(fù)讀

    a事務(wù)周期內(nèi)對某一數(shù)據(jù)多次查詢,同時(shí)這些數(shù)據(jù)在b事務(wù)中進(jìn)行了update或delete操作。那么a事務(wù)每次查詢出來的結(jié)果可能都不一樣。

  • 幻讀

    幻讀的結(jié)果其實(shí)和不可重復(fù)讀是一樣的表現(xiàn),差異就在于不可重復(fù)讀主要是針對其他事務(wù)進(jìn)行了編輯(update)和刪除(delete)操作。而幻讀主要是針對插入(insert)操作。也就是在一個(gè)事務(wù)生命周期內(nèi),會(huì)查詢到另外一個(gè)事務(wù)新插入的數(shù)據(jù)。

Read uncommitted 未提交讀

未提交讀,這種情況下,一個(gè)事務(wù)a可以看到另一個(gè)事務(wù)b未提交的數(shù)據(jù),如果此時(shí)事務(wù)b發(fā)生回滾,那么事務(wù)a拿到的就是臟數(shù)據(jù),這也就是臟讀的含義。

此隔離級別在MySQL InnoDB一般不推薦使用。

Read Committed 已提交讀

已提交讀,一個(gè)事務(wù)從開始直到提交之前,所做的任何修改對其他事務(wù)都是不可見的。解決了臟讀問題,但是存在幻讀現(xiàn)象。

Repeatable Read 可重復(fù)讀

可重復(fù)讀,該級別保證在同一事務(wù)中多次讀取同樣記錄的結(jié)果是一致的,在InnoDB存儲(chǔ)引擎中同時(shí)解決了幻讀和不可重復(fù)讀問題。

InnoDB引擎通過使用Next-Key Lock解決了幻讀的問題。Next-Key Lock是行鎖和間隙鎖的組合,當(dāng)InnoDB掃描索引記錄的時(shí)候,會(huì)首先對索引記錄加上行鎖(Record Lock),再對索引記錄兩邊的間隙加上間隙鎖(Gap Lock)。加上間隙鎖之后,其他事務(wù)就不能在這個(gè)間隙修改或者插入記錄。

Serializable 可串行化

Serializable 是最高的隔離級別,它通過強(qiáng)制事務(wù)串行執(zhí)行,避免了幻讀的問題,但是 Serializable 會(huì)在讀取的每一行數(shù)據(jù)上都加鎖,所以可能導(dǎo)致大量的超時(shí)和鎖爭用的問題,因此并發(fā)度急劇下降,在MySQL InnoDB同樣不被建議使用。

開啟事務(wù)

  • BEGIN、BEGIN WORK、START TRANSACTION

    執(zhí)行BEGIN命令不會(huì)真正在引擎層開啟新事務(wù),僅僅是為當(dāng)前線程設(shè)定標(biāo)記,表示為顯式開啟的事務(wù)。

  • START TRANSACTION READ ONLY

    開啟只讀事務(wù),當(dāng)MySQL Server接收到任何數(shù)據(jù)更改的SQL時(shí),都會(huì)直接拒絕修改并返回錯(cuò)誤,此錯(cuò)我不會(huì)進(jìn)入引擎層。

  • START TRANSACTION READ WRITE

    允許super用戶在當(dāng)前線程只讀狀態(tài)為true的情況下啟動(dòng)讀寫事務(wù)。

  • START TRANSACTION WITH CONSISTENT SNAPSHOT

    開啟事務(wù)會(huì)進(jìn)入引擎層,并開啟一個(gè)readview。只有在RR隔離級別下,這種操作才有效,否則會(huì)報(bào)錯(cuò)。

Undo log

在數(shù)據(jù)進(jìn)行修改時(shí)會(huì)記錄相應(yīng)的undo日志,如果事務(wù)失敗或者回滾,可以借助記錄的undo日志進(jìn)行回滾。Undo log是邏輯日志,記錄更改前的數(shù)據(jù)鏡像。在修改時(shí)如果同時(shí)需要讀取當(dāng)前數(shù)據(jù)的時(shí)候,它可以根據(jù)版本信息分析出該行記錄以前版本的數(shù)據(jù)。另外Undo log也會(huì)產(chǎn)生重做日志,因?yàn)閁ndo log也要進(jìn)行持久化保護(hù)。

事務(wù)提交

  1. 使用全局事務(wù)ID產(chǎn)生器生成事務(wù)NO,將當(dāng)前連接的事務(wù)指針(trx_t)添加到全局提交事務(wù)鏈表(trx_serial_list)中
  2. 標(biāo)記undo,如果這個(gè)事務(wù)只使用了一個(gè)UndoPage且使用量小于3/4個(gè)Page,則把這個(gè)Page標(biāo)記為TRX_UNDO_CACHED,如果不滿足且是insert undo則標(biāo)記為TRX_UNDO_TO_FREE,否則undo為update undo則標(biāo)記為TRX_UNDO_TO_PURGE。標(biāo)記為TRX_UNDO_CACHED的undo會(huì)被引擎回收。
  3. 把update undo放入所在undo segment的history list,并遞增rseg_history_len(全局)。同時(shí)更新Page上的TRX_UNDO_TRX_NO, 如果刪除了數(shù)據(jù),則重置delete_mark
  4. 把undate undo從update_undo_list中刪除,如果被標(biāo)記為TRX_UNDO_CACHED,則加入到update_undo_cached隊(duì)列中
  5. mtr_commit(日志undo/redo寫入公共緩沖區(qū)),至此,在文件層次事務(wù)提交。這個(gè)時(shí)候即使crash,重啟后依然能保證事務(wù)是被提交的。接下來要做的是內(nèi)存數(shù)據(jù)狀態(tài)的更新(trx_commit_in_memory)
  6. 只讀事務(wù)只需要把readview從全局readview鏈表中移除,然后重置trx_t結(jié)構(gòu)體里面的信息即可。讀寫事務(wù)首先需要是設(shè)置事務(wù)狀態(tài)為TRX_STATE_COMMITTED_IN_MEMORY,釋放所有行鎖并且將trx_t從rw_trx_list中移除,readview從全局readview鏈表中移除。如果有insert undo則在這里移除,如果有update undo則喚醒Purge線程進(jìn)行垃圾清理,最后重置trx_t里的信息,便于下一個(gè)事務(wù)使用

回滾

  • 如果是只讀事務(wù),則直接返回
  • 判斷當(dāng)前是回滾整個(gè)事務(wù)還是部分事務(wù),如果是部分事務(wù),則記錄下需要保留多少個(gè)Undo log,多余的全進(jìn)行回滾
  • 從update undo和insert undo中找出最后一條undo,從這條undo開始回滾
  • 如果是update undo則將標(biāo)記為刪除的記錄清理標(biāo)記,更新過的數(shù)據(jù)回滾到最老的版本。如果是insert undo則直接刪除聚集索引和二級索引
  • 如果所有undo都已經(jīng)被回滾或者回滾到了指定的undo則停止,把Undo log刪除

索引

InnoDB引擎使用B+樹作為索引結(jié)構(gòu),主鍵索引的葉子節(jié)點(diǎn)data域保存了完整的字段數(shù)據(jù),非主鍵索引的葉子節(jié)點(diǎn)保存了指向主鍵的值數(shù)據(jù)。

上圖是 InnoDB 主索引(同時(shí)也是數(shù)據(jù)文件)的示意圖,可以看到葉節(jié)點(diǎn)包含了完整的數(shù)據(jù)記錄,這種索引叫做聚集索引。因?yàn)?InnoDB 的數(shù)據(jù)文件本身要按主鍵聚集,所以 InnoDB 要求表必須有主鍵,如果沒有顯式指定,則 MySQL 系統(tǒng)會(huì)自動(dòng)選擇一個(gè)可以唯一標(biāo)識(shí)數(shù)據(jù)記錄的列作為主鍵,如果不存在這種列,則 MySQL 自動(dòng)為 InnoDB 表生成一個(gè)隱含字段作為主鍵,這個(gè)字段長度為6個(gè)字節(jié),類型為長整形。

InnoDB 的輔助索引 data 域存儲(chǔ)相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB 的所有輔助索引都引用主鍵作為 data 域。聚集索引這種實(shí)現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

結(jié)尾

對于MySQL InnoDB的諸多特性,本文只介紹了很小的一部分,感興趣的同學(xué)可閱讀 《MySQL技術(shù)內(nèi)幕:InnoDB存儲(chǔ)引擎》了解更多相關(guān)知識(shí)。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • MySQL 表數(shù)據(jù)的導(dǎo)入導(dǎo)出操作示例

    MySQL 表數(shù)據(jù)的導(dǎo)入導(dǎo)出操作示例

    這篇文章主要介紹了MySQL 表數(shù)據(jù)的導(dǎo)入導(dǎo)出操作,結(jié)合實(shí)例形式分析了MySQL 表數(shù)據(jù)的導(dǎo)入導(dǎo)出操作基本命令、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04
  • MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫重命名的快速且安全方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 淺談MySQL數(shù)據(jù)庫中日期中包含零值的問題

    淺談MySQL數(shù)據(jù)庫中日期中包含零值的問題

    下面小編就為大家?guī)硪黄獪\談MySQL數(shù)據(jù)庫中日期中包含零值的問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • MySQL中order?by的執(zhí)行過程

    MySQL中order?by的執(zhí)行過程

    這篇文章主要介紹了MySQL中order?by的執(zhí)行過程,一訂單表為例展開相應(yīng)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • MySQL的安裝與配置詳細(xì)教程

    MySQL的安裝與配置詳細(xì)教程

    MySQL是一種關(guān)系數(shù)據(jù)庫管理系統(tǒng),所使用的 SQL 語言是用于訪問數(shù)據(jù)庫的最常用的,本文主要以Mysql免安裝版為例,幫助大家解決安裝與配置mysql的步驟
    2021-06-06
  • MySQL MHA 運(yùn)行狀態(tài)監(jiān)控介紹

    MySQL MHA 運(yùn)行狀態(tài)監(jiān)控介紹

    這篇文章主要介紹MySQL MHA 運(yùn)行狀態(tài)監(jiān)控,MHA(Master HA)是一款開源的 MySQL 的高可用程序,它為 MySQL 主從復(fù)制架構(gòu)提供了 automating master failover 功能,想具體了解的小伙伴可以和小編一起學(xué)習(xí)下面文章內(nèi)容
    2021-10-10
  • MySQL性能優(yōu)化 出題業(yè)務(wù)SQL優(yōu)化

    MySQL性能優(yōu)化 出題業(yè)務(wù)SQL優(yōu)化

    根據(jù)用戶的作答結(jié)果出練習(xí)卷,題目的優(yōu)先級為:未做過的題目>只做錯(cuò)的題目>做錯(cuò)又做對的題目>只做對的題目。
    2010-08-08
  • MySQL之union和union all的使用及區(qū)別說明

    MySQL之union和union all的使用及區(qū)別說明

    這篇文章主要介紹了MySQL之union和union all的使用及區(qū)別說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • MySQL Hints控制查詢優(yōu)化器的選擇問題小結(jié)

    MySQL Hints控制查詢優(yōu)化器的選擇問題小結(jié)

    MySQL Hints是一種強(qiáng)大的工具,可以幫助我們解決復(fù)雜的查詢性能問題,然而,它們應(yīng)該謹(jǐn)慎使用,并且總是與徹底的測試和驗(yàn)證相結(jié)合,本文介紹MySQL Hints控制查詢優(yōu)化器的選擇,感興趣的朋友一起看看吧
    2024-06-06
  • MySQL 那些常見的錯(cuò)誤設(shè)計(jì)規(guī)范,你都知道嗎

    MySQL 那些常見的錯(cuò)誤設(shè)計(jì)規(guī)范,你都知道嗎

    今天來看一看 MySQL 設(shè)計(jì)規(guī)范中幾個(gè)常見的錯(cuò)誤例子,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-07-07

最新評論