Change Buffer
當需要更新一個數(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 中與這個頁有關的操作。通過這種方式就能保證這個數(shù)據(jù)邏輯的正確性。
需要說明的是,雖然名字叫作 change buffer,實際上它是可以持久化的數(shù)據(jù)。也就是說,change buffer 在內(nèi)存中有拷貝,也會被寫入到磁盤上。
將 change buffer 中的操作應用到原數(shù)據(jù)頁,得到最新結果的過程稱為 merge。
除了訪問這個數(shù)據(jù)頁會觸發(fā) merge 外,系統(tǒng)有后臺線程會定期 merge。在數(shù)據(jù)庫正常關閉(shutdown)的過程中,也會執(zhí)行 merge 操作。
顯然,如果能夠將更新操作先記錄在 change buffer,減少讀磁盤,語句的執(zhí)行速度會得到明顯的提升。
而且,數(shù)據(jù)讀入內(nèi)存是需要占用 buffer pool 的,所以這種方式還能夠避免占用內(nèi)存,提高內(nèi)存利用率。
那么,什么條件下可以使用 change buffer 呢?
對于唯一索引來說,所有的更新操作都要先判斷這個操作是否違反唯一性約束。
比如,要插入unique_key = 4這個記錄,就要先判斷現(xiàn)在表中是否已經(jīng)存在 unique_key=4 的記錄,而這必須要將數(shù)據(jù)頁讀入內(nèi)存才能判斷。如果都已經(jīng)讀入到內(nèi)存了,那直接更新內(nèi)存會更快,就沒必要使用 change buffer 了。
因此,唯一索引的更新就不能使用 change buffer,實際上也只有普通索引可以使用。change buffer 用的是 buffer pool 里的內(nèi)存,因此不能無限增大。change buffer 的大小,可以通過參數(shù) innodb_change_buffer_max_size 來動態(tài)設置。這個參數(shù)設置為 50 的時候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。
因此,對于數(shù)據(jù)本身就存在于內(nèi)存中的情況,那么普通和唯一索引的性能差距不大。
但是如果數(shù)據(jù)不存在內(nèi)存中,那么唯一索引由于需要把數(shù)據(jù)從磁盤讀取到內(nèi)存中,無法使用change buffer,因此性能差了很多。
通過上面的分析,我們已經(jīng)清楚了使用 change buffer 對更新過程的加速作用,也清楚了 change buffer 只限于用在普通索引的場景下,而不適用于唯一索引。
那么,現(xiàn)在有一個問題就是:
普通索引的所有場景,使用 change buffer 都可以起到加速作用嗎?
因為 merge 的時候是真正進行數(shù)據(jù)更新的時刻,而 change buffer 的主要目的就是將記錄的變更動作緩存下來,所以在一個數(shù)據(jù)頁做 merge 之前,change buffer 記錄的變更越多(也就是這個頁面上要更新的次數(shù)越多),收益就越大。
因此,對于寫多讀少的業(yè)務來說,頁面在寫完以后馬上被訪問到的概率比較小,此時 change buffer 的使用效果最好。 這種業(yè)務模型常見的就是賬單類、日志類的系統(tǒng)。反過來,假設一個業(yè)務的更新模式是寫入之后馬上會做查詢,那么即使?jié)M足了條件,將更新先記錄在 change buffer,但之后由于馬上要訪問這個數(shù)據(jù)頁,會立即觸發(fā) merge 過程。這樣隨機訪問 IO 的次數(shù)不會減少,反而增加了 change buffer 的維護代價。所以,對于這種業(yè)務模式來說,change buffer 反而起到了副作用。
Buffer Pool
MySQL 中的 Buffer Pool 是為了優(yōu)化磁盤 I/O 而引入的機制。MySQL 內(nèi)部的頁大小與操作系統(tǒng)的頁大小可以不一致,MySQL 中的頁大小通常是固定的,默認為16KB。
Buffer Pool 是一個內(nèi)存區(qū)域,用于緩存從磁盤讀取和維護的數(shù)據(jù)頁。它的作用是減少磁盤 I/O 操作,提高數(shù)據(jù)庫的性能和響應速度。當查詢或修改數(shù)據(jù)時,MySQL 首先檢查緩沖池中是否存在所需的數(shù)據(jù)頁,如果存在,則可以直接從內(nèi)存中讀取或寫入數(shù)據(jù),從而避免了頻繁的磁盤讀寫操作。
緩沖池的大小可以通過配置參數(shù) innodb_buffer_pool_size 來設置。合理設置緩沖池的大小非常重要,過小的緩沖池可能導致頻繁的磁盤 I/O,而過大的緩沖池可能浪費寶貴的內(nèi)存資源。
為了更好地使用緩沖池,可以考慮以下幾個方面:
根據(jù)系統(tǒng)的內(nèi)存大小和數(shù)據(jù)庫的訪問模式設置合適的緩沖池大小。這需要綜合考慮系統(tǒng)中其他進程和服務的內(nèi)存需求。
監(jiān)控緩沖池的使用情況,例如使用 show global status like ‘Innodb_buffer_pool%’ 命令來查看緩沖池的命中率、使用率等指標。可以根據(jù)監(jiān)控結果來調整緩沖池大小。
確保表的索引足夠優(yōu)化,以最大程度地減少對磁盤的訪問。
對于 Buffer Pool 中的數(shù)據(jù)如何保證與磁盤的數(shù)據(jù)一致性,InnoDB 引擎采用了寫前日志(Write-Ahead Logging)的機制。在修改數(shù)據(jù)之前,InnoDB 會先將修改的數(shù)據(jù)寫入日志文件(Redo Log),然后再將數(shù)據(jù)頁更新到 Buffer Pool。這樣即使系統(tǒng)崩潰或重啟,可以通過日志的恢復操作來保證數(shù)據(jù)的一致性。
(WAL)寫前日志是一種常見的數(shù)據(jù)庫事務處理策略,旨在保證數(shù)據(jù)的持久性和一致性。在MySQL中,當進行數(shù)據(jù)修改操作時,InnoDB存儲引擎首先會將修改操作寫入日志文件(稱為重做日志或者寫前日志),然后再將相應的數(shù)據(jù)頁更新到Buffer Pool中。這樣做的好處是,即使在更新到磁盤之前發(fā)生了系統(tǒng)崩潰或斷電等故障,數(shù)據(jù)庫可以根據(jù)重做日志來恢復數(shù)據(jù),保證數(shù)據(jù)的完整性和一致性。
換句話說,寫前日志機制確保了數(shù)據(jù)的持久性,而Buffer Pool則用于提高查詢性能,緩存經(jīng)常訪問的數(shù)據(jù)頁,減少對磁盤的I/O操作。兩者是協(xié)同工作的,保證了數(shù)據(jù)的安全性和數(shù)據(jù)庫的高性能運行。
在正常情況下,MySQL 會根據(jù)一定的策略將 Buffer Pool 中的數(shù)據(jù)刷新到磁盤,以確保數(shù)據(jù)的持久性。
正常情況下,MySQL會定期將Buffer Pool中的臟頁(已被修改但尚未寫入磁盤的數(shù)據(jù)頁)刷新到磁盤,以保證數(shù)據(jù)的持久性。刷新策略可以通過配置參數(shù)進行調整,如innodb_max_dirty_pages_pct和innodb_io_capacity等。
Redo Log
一言以蔽之:減少磁盤隨機寫,使用內(nèi)存高速順序寫。提供奔潰數(shù)據(jù)恢復機制。
Redo Log日志為mysql提供了crash-safe的能力,也就是奔潰恢復能力。
我們知道,我們使用mysql的時候,其性能瓶頸在于隨機的磁盤IO操作,因此如果能減少對磁盤IO的操作,那么能極大的提高性能。
我們再使用增刪改操作的時候,其實就是一種隨機IO操作,如果我們每次都把對應的操作數(shù)據(jù)從磁盤中讀取出來然后修改再寫入,那么性能可想而知的低。
所以,能不能有一種辦法,我們能先把數(shù)據(jù)寫到緩存(內(nèi)存)中,然后再合適的時機再把這些數(shù)據(jù)寫入到磁盤呢?
是有的,也就是我們所謂的Redo Log日志了。
當我們需要寫入數(shù)據(jù)的時候,我們并不是把這些數(shù)據(jù)直接寫入到磁盤,而是先寫到redo log這種更快速的內(nèi)存文件中,那么對性能的影響就會小很多了。
redo log中記錄的是對mysql中數(shù)據(jù)塊的操作。
當我們的mysql出現(xiàn)奔潰的時候,我們再次重啟進行數(shù)據(jù)恢復的時候,就可以從redo log中把這些還沒有寫道磁盤中的數(shù)據(jù)給他進行寫入,從而保證了數(shù)據(jù)一致性。
Bin Log
一言以蔽之:提供數(shù)據(jù)恢復,數(shù)據(jù)回滾,主從同步等功能。
Binlog(二進制日志)是MySQL中的一種日志文件,用于記錄數(shù)據(jù)庫的所有修改操作,例如插入、更新和刪除。Binlog具有以下幾個重要的作用和意義:
數(shù)據(jù)恢復與備份:Binlog可以用于數(shù)據(jù)的恢復與備份。通過將Binlog文件應用到MySQL實例中,可以將數(shù)據(jù)庫還原到特定的時間點或特定的事務狀態(tài)。這在數(shù)據(jù)丟失或數(shù)據(jù)庫崩潰時非常有用。
主從復制:Binlog是MySQL主從復制的基礎。在主從復制中,主數(shù)據(jù)庫上的所有修改操作都會被記錄到Binlog文件中,并通過網(wǎng)絡傳送給從數(shù)據(jù)庫。從數(shù)據(jù)庫根據(jù)Binlog文件的內(nèi)容來執(zhí)行相同的修改操作,從而保持與主數(shù)據(jù)庫的數(shù)據(jù)一致性。
數(shù)據(jù)庫同步與高可用性:Binlog可以用于實時地將變更操作傳播到其他MySQL實例,從而實現(xiàn)數(shù)據(jù)庫的同步和高可用性。通過將Binlog文件傳輸給其他MySQL實例,這些實例可以將變更操作應用到自己的數(shù)據(jù)庫中,從而保持數(shù)據(jù)的一致性。
數(shù)據(jù)分析與查詢回放:Binlog記錄了數(shù)據(jù)庫的所有修改操作,因此可以用于數(shù)據(jù)分析和查詢回放。通過分析Binlog文件,可以了解到數(shù)據(jù)庫的歷史修改操作,進行性能分析、數(shù)據(jù)統(tǒng)計等工作。對于需要重放歷史查詢的場景,可以將Binlog文件應用到測試環(huán)境中,模擬執(zhí)行查詢操作。
在MySQL中,Bin Log是用于記錄數(shù)據(jù)庫的更改操作的二進制日志。以下是會寫入Bin Log日志的操作:
DML語句(Data Manipulation Language):包括INSERT、UPDATE和DELETE語句,用于對表中的數(shù)據(jù)進行增、刪、改操作。
DDL語句(Data Definition Language):包括CREATE、ALTER和DROP語句,用于創(chuàng)建、修改和刪除數(shù)據(jù)庫對象,如表、索引等。
DCL語句(Data Control Language):包括GRANT和REVOKE語句,用于授權和撤銷權限。
數(shù)據(jù)更改函數(shù)和存儲過程:如果函數(shù)或存儲過程中包含了會修改數(shù)據(jù)的操作,那么執(zhí)行這些函數(shù)或存儲過程也會寫入Bin Log日志。
寫入Bin Log日志的目的是為了實現(xiàn)數(shù)據(jù)庫的持久性和數(shù)據(jù)恢復。通過將更改操作記錄到Bin Log中,可以在發(fā)生故障或數(shù)據(jù)丟失的情況下進行數(shù)據(jù)恢復和同步。此外,Bin Log日志還可以用于數(shù)據(jù)庫復制、數(shù)據(jù)備份、數(shù)據(jù)遷移等場景。
Undo Log
一言以蔽之:MVCC多版本并發(fā)控制的視圖所能看到的數(shù)據(jù)依賴于此。
Undo log(回滾日志)是MySQL InnoDB存儲引擎中的一部分,用于實現(xiàn)事務的原子性和一致性。它的作用是記錄事務操作的反向操作,以便在事務回滾或系統(tǒng)崩潰時,可以恢復到事務開始前的狀態(tài)。
當一個事務開始時,InnoDB會為該事務創(chuàng)建一個undo log。在事務執(zhí)行期間,如果發(fā)生了數(shù)據(jù)修改(例如插入、更新、刪除),則會在undo log中記錄相應的反向操作,以便在回滾時可以撤銷這些修改。
具體而言,對于插入操作,undo log記錄了插入的數(shù)據(jù)和哪個位置需要刪除該數(shù)據(jù);對于更新和刪除操作,undo log記錄了被修改或刪除的數(shù)據(jù)和如何還原到原有狀態(tài)的操作。
當一個事務需要回滾時,InnoDB會根據(jù)對應的undo log中的反向操作,將之前的數(shù)據(jù)修改撤銷,恢復到事務開始前的狀態(tài)。這種能力是事務的基本特性之一,保證了事務的原子性和一致性。
對于MySQL的性能影響來說,undo log會占用一定的存儲空間。每個事務的undo log都需要先寫入磁盤,這可能引起一定的IO開銷。同時,在事務并發(fā)執(zhí)行時,undo log的管理和讀寫也會引起一些額外的開銷,因此在高并發(fā)場景下,需要合理設置undo log的大小和管理策略,以保證系統(tǒng)性能的平衡。
Undo log在MySQL InnoDB存儲引擎中與多版本并發(fā)控制(MVCC)密切相關,并且在MVCC中起到重要作用。MVCC是一種并發(fā)控制機制,用于實現(xiàn)高并發(fā)環(huán)境下的事務隔離性。
MVCC通過為每個事務分配唯一的事務ID(Transaction ID)和版本號來管理事務的并發(fā)訪問。當一個事務開始時,會記錄當前數(shù)據(jù)庫中的快照版本。隨著事務的進行,其他事務可以繼續(xù)對數(shù)據(jù)庫進行讀操作,讀取快照版本的數(shù)據(jù),而不會受到當前事務所做的修改的影響。
這就引入了undo log的作用。在MVCC中,當一個事務正在對數(shù)據(jù)進行修改時,為了保證其他事務能夠讀取到一致的數(shù)據(jù),InnoDB會將修改前的數(shù)據(jù)拷貝一份到undo log中,并在undo log中記錄該操作的版本號。
當其他事務讀取數(shù)據(jù)時,如果該數(shù)據(jù)被正在進行修改的事務修改了,InnoDB會根據(jù)事務的版本號和undo log中的信息,通過回滾操作將該數(shù)據(jù)還原到修改前的狀態(tài),然后讀取這個被還原的數(shù)據(jù),保證了讀取的一致性。
因此,undo log在MVCC中的作用是提供了用于還原數(shù)據(jù)的歷史版本,以確保事務讀取的數(shù)據(jù)是一致的。它用于實現(xiàn)數(shù)據(jù)的回滾和回滾段的管理,為MVCC提供了必要的支持。
需要注意的是,MVCC不僅僅依賴于undo log,還與其他機制(如讀視圖、回滾段等)緊密結合,以實現(xiàn)事務的隔離性和并發(fā)控制。undo log作為其中的一部分,發(fā)揮了關鍵的作用。
這幾個日志的協(xié)作流程
當根據(jù)修改請求對應的數(shù)據(jù)是否在內(nèi)存中,分別對這些日志進行操作的執(zhí)行流程如下:
Change Buffer:首先,修改操作會在內(nèi)存的Change Buffer中進行記錄。Change Buffer是MySQL的一種機制,用于延遲對磁盤上對應頁的實際修改,以提高性能。修改操作在Change Buffer中被記錄下來,而不是立即寫入磁盤上的對應頁。
Buffer Pool:數(shù)據(jù)在內(nèi)存中的主要存儲位置是Buffer Pool(也稱為頁緩存)。當修改操作需要讀取數(shù)據(jù)頁時,MySQL會先檢查Buffer Pool中是否存在要修改的頁。如果存在,就直接在Buffer Pool中進行修改操作。如果要修改的頁不在Buffer Pool中,那么下次查詢出來這條數(shù)據(jù)的時候,我們就會把他加載到Buffer Pool并且使用Change Buffer里面的修改操作來對他進行操作。
Undo Log:在修改操作執(zhí)行過程中,MySQL會將對原始數(shù)據(jù)的修改操作記錄到Undo Log中。Undo Log用于回滾事務或者恢復數(shù)據(jù)到之前的版本。通過記錄修改前的數(shù)據(jù),MySQL可以在需要時撤銷或回滾修改操作。
Redo Log:同時,修改操作的日志也會寫入到Redo Log中。Redo Log是用于崩潰恢復的重要日志。它記錄了所有的修改操作,以保證即使在異常情況下數(shù)據(jù)的持久性。
Bin Log:最后,修改操作還會記錄到Bin Log(二進制日志)中。Bin Log是用于復制和恢復的日志。通過記錄修改操作,可以在主從服務器之間同步數(shù)據(jù),并且可以用于在災難恢復時恢復數(shù)據(jù)。
注意,最后寫B(tài)in Log日志以及Redo Log日志的過程涉及到兩階段提交。文章來源:http://www.zghlxwxcb.cn/news/detail-589597.html
也就是不論是否使用到Change Buffer,只要我們做了修改操作,我們就會寫入數(shù)據(jù)到redo log中文章來源地址http://www.zghlxwxcb.cn/news/detail-589597.html
到了這里,關于【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!