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

MySQL 8.0 redo log的深入解析

 更新時(shí)間:2021年03月19日 10:08:45   作者:brightdeng@DBA  
這篇文章主要介紹了MySQL 8.0 redo log的深入解析,幫助大家更好的理解和學(xué)習(xí)使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下

前言

最開始了解mysql實(shí)現(xiàn)的時(shí)候,總聽到redo log, WAL(write-ahead logging),undo log這些關(guān)鍵詞,了解到redo log主要是用于實(shí)現(xiàn)事務(wù)的持久化的。為了進(jìn)一步了解redo log,看了下相關(guān)代碼(源碼版本: mysql 8.0.12),這里簡單總結(jié)下,主要介紹redo log是如何產(chǎn)生,如何落盤,以及最終通知用戶的。

redo log的產(chǎn)生

讀寫事務(wù)在執(zhí)行的過程中,會(huì)不斷的產(chǎn)生redo log。申請數(shù)據(jù)頁、修改數(shù)據(jù)頁、記錄undo log等,都會(huì)產(chǎn)生redo log。mysql將用戶事務(wù)拆分成一個(gè)個(gè)mtr(mini transaction),redo log最初產(chǎn)生時(shí)就是被記錄到mtr中的,并伴隨著mtr的提交而提交,最終落到硬盤上。

redo log 的提交

mtr在提交時(shí),會(huì)將mtr中的redo log寫到系統(tǒng)變量log_sys的log buffer中。mysql8.0一個(gè)新特性就是redo log提交的無鎖化。在8.0以前,各個(gè)用戶線程都是通過互斥量競爭,串行的寫log buffer,因此能保證lsn的順序無間隔增長。8.0時(shí)用戶線程可以并發(fā)寫log buffer,如果某個(gè)用戶線程寫log buffer成功后,就將自己寫的lsn以前的log buffer刷盤,則有可能導(dǎo)致其他用戶線程寫log buffer還沒完成就被刷盤。

為了解決這個(gè)問題,mysql 8.0引入了Link_buf這個(gè)數(shù)據(jù)結(jié)構(gòu)來避免log buffer的空洞。Link_buf實(shí)際是一個(gè)定長數(shù)組,像滑動(dòng)窗口一樣跟蹤log buffer一段區(qū)間的寫入情況,隨著log buffer中寫入連續(xù)redo log不斷向前推進(jìn)。

Link_buf的數(shù)據(jù)結(jié)構(gòu)如圖:

當(dāng)用戶在log buffer的start_lsn-end_lsn間寫下redo log時(shí),會(huì)標(biāo)記Link_buf相應(yīng)的位置,即將m_link[start_lsn%m_capacity]賦值為為end_lsn-start_lsn。

redo log記錄到log buffer的過程如下:

1.首先,各用戶線程寫redo log時(shí),先根據(jù)redo log長度,向系統(tǒng)全局原子變量log_sys.sn獲取本次redo log日志的start_lsn, end_lsn。原子變量sn能保證各線程獲得的start_lsn-end_lsn區(qū)間連續(xù)無空洞;

2.用戶線程申請到start_lsn-end_lsn區(qū)間后,需要先等待到Link_buf推進(jìn)到自己可以使用的位置。

如圖所示,start_lsn0-end_lsn0,start_lsn2-end_lsn2, start_lsn3-end_lsn3為三個(gè)用戶線程新申請的lsn區(qū)間;start_lsn1-end_lsn1對應(yīng)的區(qū)間已經(jīng)標(biāo)記到link_buf上;start_lsn3-end_lsn3距離tail太遠(yuǎn),需要等待link_buf推進(jìn)才能使用;

3.寫入log buffer后,再將start_lsn->end_lsn的范圍標(biāo)記到link_buf(注意:因?yàn)橹辉趕tart_lsn%capacity的位置標(biāo)記link_buf,所以即使end_lsn超過(m_tail, m_tail+m_capacity)也不影響);

4.用戶線程提交事務(wù)時(shí)設(shè)置事件log_sys.writer_event,觸發(fā)log_writer線程將日志從redo log buffer寫到系統(tǒng)緩存(log_writer線程自己也會(huì)輪詢link_buf判斷是否寫入了新的日志);

5.log_writer線程推進(jìn)m_tail,并將m_tail前的log buffer落盤。

redo log 的落盤及通知

前面簡述了redo log是如何提交的,在redo log提交以及落盤時(shí),涉及多個(gè)線程,他們的關(guān)系如下:

用戶線程在讀寫事務(wù)提交時(shí),會(huì)產(chǎn)生一些redo log,并隨著mtr提交而記錄到redo log buffer中,隨后用戶線程嘗試設(shè)置writer_event觸發(fā)log_writer線程寫日志,并監(jiān)聽屬于自己的flush_events[i]事件;

log_writer線程推進(jìn)Link_buf.m_tail,將最大連續(xù)lsn前的redo log寫入系統(tǒng)緩存,并設(shè)置flusher_event觸發(fā)log_flusher線程;

log_flusher線程將已寫入系統(tǒng)緩存的日志刷盤,并設(shè)置flush_notifier_event觸發(fā)log_flush_notifier線程通知用戶;

log_flush_notifier根據(jù)已刷盤的lsn換算出需要觸發(fā)的事件,通知用戶線程。

具體實(shí)現(xiàn)時(shí),通過log_sys中的幾個(gè)成員變量,跟進(jìn)redo log的寫入情況。其中l(wèi)og_sys.recent_writtern.m_tail表示log buffer最大連續(xù)范圍;log_sys.write_lsn表示寫入到系統(tǒng)緩存的位置;log_sys.flushed_to_disk_lsn表示已落盤的位置。各標(biāo)記的推進(jìn)過程如下:

通知用戶線程

用戶提交事務(wù)時(shí),會(huì)根據(jù)innodb_flush_log_at_trx_commit參數(shù),調(diào)用log_wait_for_write或log_wait_for_flush,來等待redo log寫入到系統(tǒng)緩存或刷到硬盤。用戶線程的通知是通過log_sys.flush_events事件數(shù)組來實(shí)現(xiàn)的,為了避免一次通知的flush_events過多,flush_events會(huì)像桶一樣劃分給不同的用戶線程:redo log是以一個(gè)個(gè)log block劃分的,假設(shè)log_sys.flush_events數(shù)組長度為m,則第n個(gè)log block的刷盤,由flush_events[n%m]事件監(jiān)聽。當(dāng)log buffer的第L1個(gè)log block到第L2個(gè)log block被刷盤時(shí),會(huì)設(shè)置L1-L2之間的log block所屬的flush_events,從而redo log在L1-L2之間的用戶線程都會(huì)收到通知。

總結(jié)

mysql8.0通過redo log無鎖化,解決了用戶線程寫redo log時(shí)競爭鎖帶來的性能影響。同時(shí)將redo log寫文件、redo log刷盤從用戶線程中剝離出來,抽成單獨(dú)的線程,用戶線程只負(fù)責(zé)將redo log寫入到log buffer,不再關(guān)心redo log的落盤細(xì)節(jié),只需等待log_writer線程或log_flusher線程的通知。

以上就是MySQL 8.0 redo log的深入解析的詳細(xì)內(nèi)容,更多關(guān)于MySQL 8.0 redo log的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Canal進(jìn)行MySQL到MySQL數(shù)據(jù)庫全量+增量同步踩坑指南

    Canal進(jìn)行MySQL到MySQL數(shù)據(jù)庫全量+增量同步踩坑指南

    這篇文章主要介紹了使用Canal作為遷移工具,將數(shù)據(jù)庫從A服務(wù)器遷移至B服務(wù)器,為了盡量減少遷移導(dǎo)致的停機(jī)時(shí)間,考慮使用全量遷移+增量同步的方式
    2023-10-10
  • 解決mysql ERROR 1017:Can''t find file: ''/xxx.frm'' 錯(cuò)誤

    解決mysql ERROR 1017:Can''t find file: ''/xxx.frm'' 錯(cuò)誤

    如果重啟服務(wù)器前沒有關(guān)閉mysql,MySql的MyiSAM表很有可能會(huì)出現(xiàn) ERROR #1017 :Can't find file: '/xxx.frm' 的錯(cuò)誤
    2011-08-08
  • MySQL 清除表空間碎片的實(shí)例詳解

    MySQL 清除表空間碎片的實(shí)例詳解

    這篇文章主要介紹了MySQL 清除表空間碎片的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-10-10
  • 使用Rotate Master實(shí)現(xiàn)MySQL 多主復(fù)制的實(shí)現(xiàn)方法

    使用Rotate Master實(shí)現(xiàn)MySQL 多主復(fù)制的實(shí)現(xiàn)方法

    眾所周知,MySQL只支持一對多的主從復(fù)制,而不支持多主(multi-master)復(fù)制
    2012-05-05
  • MySQL中的間隙鎖代碼示例講解

    MySQL中的間隙鎖代碼示例講解

    鎖是mysql提供的一種保證不同事務(wù)讀寫隔離的重要措施,通過鎖機(jī)制可以有效提升決多線程下并發(fā)處理事務(wù)能力,不同的鎖劃分對應(yīng)著不同的使用場景,本文來深入探討一下mysql的另一種容易被忽視的鎖,即間隙鎖,以及與之相關(guān)的相關(guān)問題,需要的朋友可以參考下
    2023-08-08
  • MySQL索引失效的典型案例

    MySQL索引失效的典型案例

    索引在我們使用MySQL數(shù)據(jù)庫時(shí)可以極大的提高查詢效率,然而,有時(shí)候因?yàn)槭褂蒙系囊恍╄Υ镁蜁?huì)導(dǎo)致索引的失效,無法達(dá)到我們使用索引的預(yù)期效果,今天介紹一種MySQL中幾種常見的索引失效的原因,可以在以后的工作中盡可能避免因索引失效帶來的坑。
    2021-06-06
  • MySQL 中定義和使用變量的方法

    MySQL 中定義和使用變量的方法

    MySQL 提供了多種類型的變量,以適應(yīng)不同的應(yīng)用場景,用戶定義的變量適用于簡單的會(huì)話內(nèi)數(shù)據(jù)傳遞,局部變量適合在復(fù)雜的存儲過程中使用,而會(huì)話變量則用于調(diào)整和優(yōu)化數(shù)據(jù)庫會(huì)話的行為,這篇文章主要介紹了MySQL 中定義和使用變量,需要的朋友可以參考下
    2024-04-04
  • Mysql 索引從入門到精通(從原理到實(shí)踐)

    Mysql 索引從入門到精通(從原理到實(shí)踐)

    本文介紹MySQL索引深度解析:從原理到實(shí)踐,本文涵蓋索引基礎(chǔ)概念、類型、底層原理及管理策略,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • Navicat自動(dòng)備份MySQL數(shù)據(jù)的流程步驟

    Navicat自動(dòng)備份MySQL數(shù)據(jù)的流程步驟

    對于從事IT開發(fā)的工程師,數(shù)據(jù)備份我想大家并不陌生,這件工程太重要了!對于比較重要的數(shù)據(jù),我們希望能定期備份,每天備份1次或多次,或者是每周備份1次或多次,所以本文給大家介紹了Navicat自動(dòng)備份MySQL數(shù)據(jù)的流程步驟,需要的朋友可以參考下
    2024-12-12
  • 基于MySql的擴(kuò)展功能生成全局ID

    基于MySql的擴(kuò)展功能生成全局ID

    本文借用 MySQL的擴(kuò)展功能 REPLACE INTO 來生成全局id,REPLACE INTO和INSERT的功能一樣,但是當(dāng)使用REPLACE INTO插入新數(shù)據(jù)行時(shí),如果新插入的行的主鍵或唯一鍵(UNIQUE Key)已有的行重復(fù)時(shí),已有的行會(huì)先被刪除,然后再將新數(shù)據(jù)行插入
    2015-12-12

最新評論

错那县| 柘城县| 象州县| 巴塘县| 北流市| 清徐县| 龙陵县| 安乡县| 娄底市| 合川市| 梅河口市| 徐闻县| 从化市| 珲春市| 铜山县| 沙田区| 郴州市| 青州市| 定西市| 临泉县| 芷江| 南靖县| 静安区| 万山特区| 蚌埠市| 徐水县| 三门峡市| 桂平市| 桃园市| 射阳县| 安陆市| 江口县| 甘孜| 盐城市| 阳朔县| 荔波县| 宣武区| 武夷山市| 韩城市| 广德县| 闽清县|