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

MySQL保證數(shù)據(jù)不丟失的方案詳解

 更新時(shí)間:2023年12月21日 09:59:07   作者:王二蛋!  
MySQL作為一個(gè)存儲(chǔ)數(shù)據(jù)的產(chǎn)品,怎么確保數(shù)據(jù)的持久性和不丟失才是最重要的,感興趣的可以跟隨本文一探究竟,文中通過(guò)圖文結(jié)合給大家講解的非常詳細(xì),需要的朋友快來(lái)跟著小編一起來(lái)學(xué)習(xí)吧

Buffer Pool 和 DML 的關(guān)系

InnoDB中的「Buffer Pool」除了在查詢時(shí)起到提高效率作用,同樣,在insert、update、delete這些DML操作時(shí)為了減少和磁盤(pán)的頻繁交互,也會(huì)將這些更新先在Buffer Pool中緩存的數(shù)據(jù)頁(yè)進(jìn)行操作,隨后將這些有更新的「臟頁(yè)」刷到磁盤(pán)中。

這個(gè)時(shí)候就涉及到一個(gè)問(wèn)題:如果MySQL服務(wù)宕機(jī)了,這些在內(nèi)存中更新的數(shù)據(jù)會(huì)不會(huì)丟失?

答案是一定會(huì)存在丟失現(xiàn)象的,只不過(guò)MySQL做到了盡量不讓數(shù)據(jù)丟失。接下來(lái)來(lái)看一下MySQL是怎么做的。

這里還是把結(jié)構(gòu)圖貼一下,方便下面介紹時(shí)看圖理解。

在這里插入圖片描述

DML操作流程

加載數(shù)據(jù)頁(yè)

通過(guò)上文可以知道,行記錄是在數(shù)據(jù)頁(yè)中,所以,當(dāng)InnoDB接收到DML操作請(qǐng)求后,還是會(huì)去找「數(shù)據(jù)頁(yè)」,查找的過(guò)程跟上文查詢行記錄流程是一樣。這里說(shuō)一下,insert的請(qǐng)求會(huì)根據(jù)主鍵索引去找數(shù)據(jù)頁(yè),update、delete根據(jù)查詢條件去找數(shù)據(jù)頁(yè),總之「數(shù)據(jù)頁(yè)」要加載到「Buffer Pool」之后才會(huì)進(jìn)行下一步操作。

更新記錄

定位到數(shù)據(jù)頁(yè)后,insert操作就是往數(shù)據(jù)頁(yè)中添加一行記錄,delete是標(biāo)記一下行記錄的‘刪除標(biāo)記’,而update則是先刪除再添加,這是因?yàn)榇嬖诳勺冮L(zhǎng)的字段類(lèi)型,比如varchar,每次更新時(shí),這種類(lèi)型的數(shù)據(jù)占用內(nèi)存是不固定的,所以先刪除再添加。

這里的刪除標(biāo)記是行記錄的字段,也就是除了業(yè)務(wù)字段數(shù)據(jù),InnoDB默認(rèn)為每行記錄添加的字段,所以一個(gè)行記錄大概如下圖,這也是之前提到過(guò)的「行格式」。

在這里插入圖片描述

找到數(shù)據(jù)頁(yè)并且更新記錄之后DML操作就算完成了,但是還沒(méi)有落地到磁盤(pán)。

這個(gè)時(shí)候直接刷新到磁盤(pán)視為完成不可以嗎?

數(shù)據(jù)持久化方案

可以是可以,但是如果每次的DML操作都要將一個(gè)16KB的數(shù)據(jù)頁(yè)刷到磁盤(pán),其效率是極低的,估計(jì)也就沒(méi)有人用MySQL了。但是如果不刷新到磁盤(pán),就會(huì)發(fā)生MySQL服務(wù)宕機(jī)數(shù)據(jù)會(huì)丟失現(xiàn)象。MySQL在這里的處理方案是:

  • 等待合適的時(shí)機(jī)將批量的「臟頁(yè)」異步刷新到磁盤(pán)。
  • 先快速將更新的記錄以日志的形式刷新到磁盤(pán)。

先看第一點(diǎn),什么時(shí)候是合適的時(shí)機(jī)?

合適的時(shí)機(jī)刷盤(pán)

當(dāng)「臟頁(yè)」在「Buffer Pool」中達(dá)到某個(gè)閾值的時(shí)候,InnoDB會(huì)將這些臟頁(yè)刷新到磁盤(pán)中。這個(gè)閾值可以通過(guò) innodb_max_dirty_pages_pct 這個(gè)參數(shù)查看或設(shè)置,相關(guān)命令如下:

-- 查看臟頁(yè)刷新閾值
show variables like 'innodb_max_dirty_pages_pct'
-- 在線設(shè)置臟頁(yè)刷新閾值,當(dāng)臟頁(yè)在Buffer Pool占用70%的時(shí)候刷新
SET GLOBAL innodb_max_dirty_pages_pct = 70

在這里插入圖片描述

當(dāng)然,這個(gè)合適的時(shí)機(jī)只是為了減少與磁盤(pán)的交互,用來(lái)提高性能的,并不能確保數(shù)據(jù)不丟失。

雙寫(xiě)機(jī)制

在刷新「臟頁(yè)」這里還有一個(gè)非常重要的注意事項(xiàng)就是:因?yàn)镮nnoDB的頁(yè)大小為16KB,而一般操作系統(tǒng)的頁(yè)大小為4KB。意味著InnoDB將這些「臟頁(yè)」向磁盤(pán)刷新時(shí),在操作系統(tǒng)層面會(huì)被分成4個(gè)4KB的頁(yè),這樣的話,如果其中有一頁(yè)因?yàn)镸ySQL宕機(jī)或者其他異常導(dǎo)致沒(méi)有成功刷新到磁盤(pán),就會(huì)出現(xiàn)「頁(yè)損壞現(xiàn)象」,數(shù)據(jù)也就不完整了。

在這里插入圖片描述

所以InnoDB在這里采用的雙寫(xiě)機(jī)制,在將這些「臟頁(yè)」刷新到磁盤(pán)之前先會(huì)往結(jié)構(gòu)圖中的「Doublewrite Buffer」中寫(xiě)入,隨后再刷新到對(duì)應(yīng)的表空間中,當(dāng)出現(xiàn)故障時(shí)就可以通過(guò)雙寫(xiě)緩沖區(qū)進(jìn)行恢復(fù)。

向「Doublewrite Buffer」就不會(huì)發(fā)生「頁(yè)損壞現(xiàn)象」?

Doublewrite Buffer」的大小是獨(dú)立且固定的,不是基于頁(yè)的大小來(lái)劃分的。所以不受操作系統(tǒng)中的頁(yè)大小限制,也不會(huì)發(fā)生「頁(yè)損壞現(xiàn)象」。并且先以順序IO的方式向「Doublewrite Buffer」寫(xiě)入數(shù)據(jù)頁(yè),再以隨機(jī)IO異步刷新到表空間這種方式還可以提高寫(xiě)入性能。

在這里插入圖片描述

再看第二點(diǎn),為什么以日志的形式先刷新到磁盤(pán)?

日志先行機(jī)制

在「Buffer Pool」中更新完數(shù)據(jù)頁(yè)后,由于不會(huì)及時(shí)將這些「臟頁(yè)」刷新到磁盤(pán),為了避免數(shù)據(jù)丟失,會(huì)將本次的DML操作向「Log Buffer」中寫(xiě)一份并且刷新到磁盤(pán)中,相比16KB的數(shù)據(jù)頁(yè)來(lái)說(shuō),這個(gè)數(shù)據(jù)量會(huì)小很多,而且寫(xiě)入日志文件時(shí)是追加操作,屬于順序IO,效率較高。如下圖,哪種方式寫(xiě)入效率更高是顯而易見(jiàn)的。

在這里插入圖片描述

這里說(shuō)的日志文件就是經(jīng)常會(huì)聽(tīng)到的「Redo Log」,即使MySQL宕機(jī)了,通過(guò)磁盤(pán)的redolog,也可以在MySQL啟動(dòng)時(shí)盡可能的將數(shù)據(jù)恢復(fù)到宕機(jī)之前樣子。當(dāng)然,還有「Undo Log」,因?yàn)閷?duì)本文重點(diǎn)沒(méi)有直接影響,所以不對(duì)此展開(kāi)說(shuō)明。

這種日志先行(WAL)的機(jī)制也是MySQL用于提高效率和保障數(shù)據(jù)可靠的一種方式。

為什么是盡可能的恢復(fù)?

日志刷盤(pán)機(jī)制

因?yàn)椤?strong>Log Buffer」中的日志數(shù)據(jù)什么時(shí)候向磁盤(pán)刷新則是由 innodb_flush_log_at_trx_commitinnodb_flush_log_at_timeout 這兩個(gè)參數(shù)決定的。

  • innodb_flush_log_at_trx_commit默認(rèn)為1,也就是每次事務(wù)提交后就會(huì)刷新到磁盤(pán)。
  • 當(dāng)innodb_flush_log_at_trx_commit設(shè)置為0時(shí),則不會(huì)根據(jù)事務(wù)提交來(lái)刷新,而是根據(jù)innodb_flush_log_at_timeout設(shè)置的時(shí)間定時(shí)刷新,這個(gè)時(shí)間默認(rèn)為1秒。
  • 當(dāng)innodb_flush_log_at_trx_commit設(shè)置為2時(shí),僅將日志寫(xiě)入操作系統(tǒng)中的緩存中,隨后跟隨根據(jù)innodb_flush_log_at_timeout定時(shí)刷新。

如果在MySQL服務(wù)宕機(jī)的時(shí)候,「Log Buffer」中的日志沒(méi)有刷新到磁盤(pán),這部分?jǐn)?shù)據(jù)也是會(huì)丟失的,在重啟后也不會(huì)恢復(fù)。所以如果不想丟失數(shù)據(jù),在性能還可以的情況下,盡量將innodb_flush_log_at_trx_commit設(shè)置為1。

「redo log」是怎么恢復(fù)數(shù)據(jù)的?

Redo Log 恢復(fù)數(shù)據(jù)

首先,redo log會(huì)記錄DML的操作類(lèi)型、數(shù)據(jù)的表空間、數(shù)據(jù)頁(yè)以及具體操作內(nèi)容,以 insert into t1(1,'hi')為例,對(duì)應(yīng)的redo log內(nèi)容大概這樣的

在這里插入圖片描述

假如 innodb_flush_log_at_trx_commit 的值為1,那么當(dāng)該DML操作事務(wù)提交后,就會(huì)將 redo log 刷新到磁盤(pán)。成功刷新到磁盤(pán)后,就可以視為數(shù)據(jù)被寫(xiě)入成功。

此時(shí)如果「臟頁(yè)」還沒(méi)刷新到磁盤(pán)便宕機(jī),那么在下次MySQL啟動(dòng)時(shí)便去加載redo log,如果redo log存在數(shù)據(jù)則意味著需要恢復(fù)數(shù)據(jù)。這個(gè)時(shí)候就可以通過(guò)redo log中的內(nèi)容重新構(gòu)建「臟頁(yè)」,從而恢復(fù)到宕機(jī)之前的狀態(tài)。

怎么構(gòu)建「臟頁(yè)」呢?

其實(shí)在每次的redo log寫(xiě)入時(shí)都會(huì)記錄一個(gè)「LSN(log sequence number)」,同時(shí)這個(gè)值在「數(shù)據(jù)頁(yè)」中記錄最后一次被修改的日志序列位置。MySQL在啟動(dòng)時(shí)通過(guò)LSN來(lái)對(duì)比 redo log 和數(shù)據(jù)頁(yè),如果數(shù)據(jù)頁(yè)中的LSN小于 redo log 的LSN,則會(huì)將該數(shù)據(jù)頁(yè)加載到「Buffer Pool」,然后根據(jù) redo log 的內(nèi)容構(gòu)建出「臟頁(yè)」,等待下次刷新到磁盤(pán),數(shù)據(jù)也就恢復(fù)了。如下圖

在這里插入圖片描述

注意:這個(gè)恢復(fù)的過(guò)程重點(diǎn)在redo上,實(shí)際上還涉及到「Change Buffer」、「Undo Log」等操作,這里沒(méi)有展開(kāi)說(shuō)明。

「Doublewrite Buffer」和「redo log」都是恢復(fù)數(shù)據(jù)的,不沖突嗎?

不沖突,「Doublewrite Buffer」是對(duì)「頁(yè)損壞現(xiàn)象」的整個(gè)數(shù)據(jù)頁(yè)進(jìn)行恢復(fù),Redo Log只能對(duì)某次的DML操作進(jìn)行恢復(fù)。

總結(jié)

InnoDB通過(guò)以上的操作可以盡可能的保證MySQL不丟失數(shù)據(jù),最后再總結(jié)一下MySQL是如何保障數(shù)據(jù)不丟失的:

  • 為了避免頻繁與磁盤(pán)交互,每次DML操作先在「Buffer Pool」中的緩存頁(yè)中執(zhí)行,緩存頁(yè)有更新之后便成為「臟頁(yè)」,隨后根據(jù)innodb_max_dirty_pages_pct這個(gè)參數(shù)將「臟頁(yè)」刷新到磁盤(pán)。
  • 因?yàn)椤?strong>臟頁(yè)」在刷新到磁盤(pán)之前可能會(huì)存在MySQL宕機(jī)等異常行為導(dǎo)致數(shù)據(jù)丟失,所以MySQL采用日志先行(WAL)機(jī)制,將DML操作以日志的形式進(jìn)行記錄到「Redo Log」中,隨后根據(jù)innodb_flush_log_at_trx_commitinnodb_flush_log_at_timeout這兩個(gè)參數(shù)將「Redo Log」刷新到磁盤(pán),以便恢復(fù)。
  • 在向磁盤(pán)刷新「臟頁(yè)」時(shí),為了避免發(fā)生「頁(yè)損壞」現(xiàn)象,InnoDB采用雙寫(xiě)機(jī)制,先將這些臟頁(yè)順序?qū)懭搿?strong>Doublewrite Buffer」中,隨后再將數(shù)據(jù)頁(yè)異步刷新到各個(gè)表空間中,這種方式既能提高寫(xiě)入效率,又可以保障數(shù)據(jù)的完整性。
  • 如果在「臟頁(yè)」刷新到磁盤(pán)之前,MySQL宕機(jī)了,那么會(huì)在下次啟動(dòng)時(shí)通過(guò) redo log 將臟頁(yè)構(gòu)建出來(lái),做到數(shù)據(jù)恢復(fù)。
  • 通過(guò)以上步驟,MySQL做到了盡可能的不丟失數(shù)據(jù)。

以上就是MySQL保證數(shù)據(jù)不丟失的方案詳解的詳細(xì)內(nèi)容,更多關(guān)于MySQL保證數(shù)據(jù)不丟失的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mysql根據(jù)某層部門(mén)ID查詢所有下級(jí)多層子部門(mén)的示例

    Mysql根據(jù)某層部門(mén)ID查詢所有下級(jí)多層子部門(mén)的示例

    這篇文章主要介紹了Mysql根據(jù)某層部門(mén)ID查詢所有下級(jí)多層子部門(mén)的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 詳解MySQL插入和查詢數(shù)據(jù)的相關(guān)命令及語(yǔ)句使用

    詳解MySQL插入和查詢數(shù)據(jù)的相關(guān)命令及語(yǔ)句使用

    這篇文章主要介紹了MySQL插入和查詢數(shù)據(jù)的相關(guān)命令及語(yǔ)句使用,包括相關(guān)的PHP腳本操作方法講解也很詳細(xì),需要的朋友可以參考下
    2015-11-11
  • 安裝Mysql找不到Bin文件的問(wèn)題解決

    安裝Mysql找不到Bin文件的問(wèn)題解決

    在解壓MySQL壓縮包后,有時(shí)會(huì)發(fā)現(xiàn)沒(méi)有bin目錄,本文主要介紹了安裝Mysql找不到Bin文件的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • Mysql存儲(chǔ)引擎詳解

    Mysql存儲(chǔ)引擎詳解

    存儲(chǔ)引擎其實(shí)就是如何實(shí)現(xiàn)存儲(chǔ)數(shù)據(jù),如何為存儲(chǔ)的數(shù)據(jù)建立索引以及如何更新,查詢數(shù)據(jù)等技術(shù)實(shí)現(xiàn)的方法。本文我們來(lái)詳細(xì)探討下MySQL中的幾個(gè)存儲(chǔ)引擎(MyISAM、InnoDB、archive、MERGE)的相關(guān)知識(shí)
    2016-12-12
  • mysql 控制臺(tái)操作

    mysql 控制臺(tái)操作

    其實(shí)MYSQL的對(duì)數(shù)據(jù)庫(kù)的操作與其它的SQL類(lèi)數(shù)據(jù)庫(kù)大同小異,您最好找本將SQL的書(shū)看看。
    2009-06-06
  • MYSQL無(wú)法連接 提示10055錯(cuò)誤的解決方法

    MYSQL無(wú)法連接 提示10055錯(cuò)誤的解決方法

    這篇文章主要介紹了MYSQL無(wú)法連接 提示10055錯(cuò)誤的解決方法,需要的朋友可以參考下
    2016-12-12
  • mysql千萬(wàn)級(jí)數(shù)據(jù)量根據(jù)索引優(yōu)化查詢速度的實(shí)現(xiàn)

    mysql千萬(wàn)級(jí)數(shù)據(jù)量根據(jù)索引優(yōu)化查詢速度的實(shí)現(xiàn)

    這篇文章主要介紹了mysql千萬(wàn)級(jí)數(shù)據(jù)量根據(jù)索引優(yōu)化查詢速度的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • mysql5.7中的密碼忘記如何找回

    mysql5.7中的密碼忘記如何找回

    這篇文章主要介紹了mysql5.7中的密碼忘記如何找回問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • MySql安裝步驟圖文教程及中文亂碼的解決方案

    MySql安裝步驟圖文教程及中文亂碼的解決方案

    這篇文章主要介紹了MySql安裝步驟圖文教程及中文亂碼的解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • Mysql?sql?如何對(duì)行數(shù)據(jù)求和

    Mysql?sql?如何對(duì)行數(shù)據(jù)求和

    這篇文章主要介紹了Mysql使用sql實(shí)現(xiàn)對(duì)行數(shù)據(jù)求和問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2023-05-05

最新評(píng)論