久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    Mysql 是什么?架構是怎么樣的?

     格瑞思n5c5alhf 2025-01-12 發布于山東
    Image

    作者 | 小白

    出品 | 小白debug(ID:xiaobaidebug)

    你是一個程序員,你做了一個網站應用,站點里的用戶數據,需要存到某個地方,方便隨時讀寫。

    很容易想到可以將數據存到文件里。

    但如果數據量很大,想從大量文件數據中查找某部分數據,并更新,是一件很痛苦的事情。

    那么問題就來了,有辦法可以解決這個問題嗎?

    好辦,沒有什么是加一層中間層不能解決的,如果有,那就再加一層

    這次我們要加的中間層是 mysql

    Image
    mysql是數據和應用的中間層

    什么是 mysql

    Mysql數據庫,是一款存放和管理數據的軟件, 它介于應用數據之間,通過一些設計,將大量數據,變成一張張像 excel 的數據表。為應用提供創建(Create), 讀取(Read), 更新(Update), 刪除(Delete)等核心操作。

    Image
    mysql是什么

    我們來看下它是怎么實現的。

    數據頁

    mysql 將數據組織成 excel 表的樣子。

    excel 文件在磁盤上是個xls 文件,mysql 的數據表也類似,在磁盤上則是個ibd 后綴的文件。

    Image
    ibd文件是什么

    數據表越大,磁盤上的 ibd 文件也就越大。

    直接讀寫一個大文件里的全部數據會很慢,所以 MySQL 將數據拆成一個個數據頁,每頁大小 16KB。這樣我們讀寫部分表數據的時候,就只需要讀取磁盤里的幾個數據頁就好。

    Image
    mysql將文件分成多個數據頁

    索引

    但數據頁那么多,查某條數據時,怎么知道要讀哪些數據頁?

    好辦,可以為每個數據頁加入頁號,再為每行數據加個序號,這個序號其實就是所謂的主鍵。

    按主鍵大小排序,將每個數據頁里最小的主鍵序號和所在頁的頁號提出來,放入到一個新生成的數據頁中,并且給數據頁加入層級的概念。

    這樣我們就可以通過上層的數據頁快速縮小查找范圍,加速查找數據頁的過程。

    現在頁跟頁之間看起來就像是一棵倒過來的樹,這棵可以加速查找數據頁的樹,就是我們常說的B+樹索引。

    Image
    B+樹索引

    上面提到的是針對主鍵的索引,也就是主鍵索引

    Image
    主鍵索引

    按同樣的思路,也可以為其他數據表的列去建立索引,比如用戶表的名稱字段,這樣我們就能快速查找到名字為 xx 的用戶有哪些,這就是所謂的輔助索引

    Image
    輔助索引

    Buffer Pool

    但就算有了索引,數據也還是在磁盤上。每次都讀磁盤太慢了。有辦法提升下性能嗎?

    有!在磁盤數據應用之間,加一層進程內緩存,緩存里裝的就是前面提到的 16KB 數據和索引頁, 它就是所謂的 Buffer Pool

    Image
    buffer pool是什么

    讀數據的時候優先讀 Buffer Pool,有數據就返回,沒數據才去磁盤里讀取,減少了讀磁盤的次數,大大提升了性能。

    但問題就來了,我們知道,文件讀取,默認會先將文件數據加載到操作系統的文件緩存中,同樣都是緩存,為什么還要整 Buffer Pool 這死出?

    這是因為進程自己維護的 Buffer Pool ,可以定制更多緩存策略,還能實現加鎖等各種數據表高級特性。

    也正是因為已經有了 Buffer Pool,所以也就沒必要使用操作系統的文件緩存了,所以 Buffer Pool 通過'直接 I/O' 模式, 繞過操作系統的緩存機制,直接從磁盤讀寫數據。

    Image
    buffer pool直接IO

    自適應 hash 索引

    就算有了 buffer pool,要查到某個數據頁,也依然要查找 B+樹,查詢復雜度 O(lgn)。能更快嗎?

    能!可以使用查詢復雜度為 **O(1)**的 hash 表進行優化。

    記錄每個數據頁的查詢頻率,對于熱點數據頁,我們以查詢的為 key數據頁地址為 value,構建 hash 表。

    比如name為 'xiaobai' 的數據頁,被頻繁查詢,那 key 就是 xiaobai,value 就是包含 xiaobai 記錄的數據頁的地址。

    Image
    哈希的key和value

    這個 hash 表,就是所謂的自適應哈希索引Adaptive Hash Index

    Image
    自適應哈希

    Change Buffer

    有了自適應 hash 索引的加持,讀性能提高了。那寫性能也能優化嗎?

    能!

    大部分數據表,除了主鍵索引外,我們還會加一些輔助索引。比如對用戶名加個輔助索引

    那對于這類數據表的寫操作,更新完主鍵索引的數據頁之后,還需要更新輔助索引頁。這樣讀取輔助索引頁的磁盤 IO 必然少不了。

    Image
    更新主鍵和輔助索引

    怎么辦呢?我們可以先將要寫入的數據收集到一塊內存里,等哪天磁盤里的索引頁正好被讀入 Buffer pool 的時候,再將寫入數據應用到索引頁中。

    通過這個方式減少大量的磁盤 IO,提升性能。

    而這個將寫操作收集起來的地方,就是所謂的 Change Buffer,它其實是 Buffer pool 的一部分。

    Image
    Change Buffer的更新流程

    Undo Log

    在數據庫中,有一個叫事務的概念。不了解沒關系,說白了,就是可以讓多行數據,要么同時更新成功,要么同時更新失敗。也就是所謂的原子性

    Image
    事務是什么

    為了實現這一點,我們就需要知道寫數據時每行數據原來長啥樣,方便對更新后的數據行,進行回滾,因此就有了 Undo Log

    Image
    undo log回滾

    更新 buffer pool 數據頁的時候,

    會用舊數據生成 undo log 記錄,存儲在 Buffer Pool 中的特殊 undo log 內存頁中。

    并隨著 buffer pool 的刷盤機制,不定時寫入到磁盤的 undo log 文件中。

    Image
    undo log的寫入流程

    Redo Log

    上面提到的都是 buffer pool 相關的內容,它們本質上都是內存。

    如果內存數據只寫了一半到磁盤中,數據庫進程就崩了,那一個事務里的多行數據就沒能做到'同時更新成功'。

    怎么辦呢?

    好辦,我們將事務中更新數據行的操作都寫入到 redo log buffer 內存中,然后在事務提交的時候進行 redo log 刷磁盤,將數據固化到 redo log 文件中。

    數據庫進程崩潰重啟后,就能通過 redo log file 找到歷史操作記錄,重做數據。保證了事務里的多行數據變更,要么都成功,要么都失敗。

    Image
    redo log的寫入流程

    這時候問題就來了,我有這功夫更新 redo log file 文件,直接將 buffer pool 的數據寫入到磁盤不香嗎?

    Image
    為什么不直接寫磁盤數據頁

    不太一樣,redo log file 是順序寫入的,buffer pool 的內存數據是隨機分散在磁盤各處的,順序寫磁盤性能是隨機寫的幾十倍,所以很多存儲系統在寫數據時都會搞個日志來記錄操作,方便服務重啟后進行數據對賬,確保數據的一致性和完整性,這類操作就是所謂的 Write-Ahead Logging (WAL) 。

    Image
    順序寫比隨機寫快很多

    但問題又來了,redo log buffer 也是內存,buffer pool 也是內存,如果 redo log buffer 里的數據還沒來得及寫入到 redo log,數據庫進程就崩了,那 redo log buffer 里的數據不也丟了嗎?

    是的,所以 redo log 的作用并不是保證所有數據不丟失,而是確保已提交事務的變更不會丟失。但因為 redo log 刷盤頻率很高,所以丟失數據的概率很低。

    redo log 本質上是寫入性能和數據完整性折中的產物,做架構就是這樣,做到最后總是需要通過犧牲某些東西去換取另一樣東西,果然,程序員才是真正的煉金術師。

    Innodb 是什么

    我們將上面提到的內容,分為內存磁盤兩部分,一部分是內存里的自適應哈希,buffer pool,以及 redo log buffer。另一部分是磁盤里存放行數據和索引的.ibd 文件, 以及 undo log, redo log 等文件。它們共同構成了 innodb 存儲引擎。并對外提供一系列函數接口。

    比如操作數據行的 write_row(), update_row(),以及操作數據表的 create(), drop()等等接口。

    我們平時寫的 SQL 語句,最終都會轉換成 InnoDB 提供的這些接口函數調用。

    Image
    innodb提供的函數接口

    比如:

    • · INSERT 語句會調用 write_row() 接口來插入數據行。

    • · UPDATE 語句會調用 update_row() 接口來更新數據行。

    • · CREATE TABLE 語句會調用 create() 接口來創建新表。

    • · DROP TABLE 語句會調用 drop() 接口來刪除表。

    但問題就來了,我們平時讀寫 mysql 用的 sql 語句,是怎么轉成存儲引擎的函數接口的呢?

    那就需要介紹 Server 層了。

    Server 層是什么

    Server 層,本質上是 sql 語句 和 innodb 存儲引擎之間的中間層。

    Image
    server層

    在 Server 層內提供一個連接管理模塊,用于管理來自應用的網絡連接。

    并提供一個分析器,用于判斷 SQL 語句有沒有語法錯誤,比如 select,是不是少打了一個l

    再提供一個優化器,用于根據一定的規則選擇該用什么索引,生成執行計劃。

    之后,提供一個執行器,根據執行計劃去調用Innodb 存儲引擎的接口函數。

    Image
    server層做了哪些事情

    server 層存儲引擎層共同構成了一個完整的數據庫,它就是我們常說的 Mysql 數據庫

    Image
    mysql是什么

    并且,server 層和存儲引擎層是通過接口函數進行解耦的,換句話說就是,只要實現了上面這些接口函數,就能作為存儲引擎與 Server 層對接。

    Image
    引擎解耦

    比如,mysql 早期用的是 myisam 存儲引擎,后來才支持的 innodb

    Image
    常用存儲引擎有哪些

    binlog 是什么

    你聽說過刪庫跑路吧,為了防止數據庫表被刪除帶來的影響, server 層會將歷史上所有變更操作記錄到磁盤上的日志文件中,這個日志文件就是所謂的 binlog。一旦誤刪表,就可以利用 binlog 來恢復數據。

    那么問題就來了,innodb 有一個 redo log 也做類似的事情,為什么還要多此一舉?評論區告訴我答案。

    這是因為 redo log 是環狀寫入的,后面寫的內容最終會覆蓋前面的內容,也就是不會記錄所有歷史寫操作,而 binlog 卻會記錄所有歷史變更。并且 binlog 位于 server 層,這樣不管底層的存儲引擎是什么,都能復用這部分能力。

    Image
    binlog寫入流程

    Mysql 主從架構

    由于 binlog 記錄了一個 mysql 的所有變更操作,因此我們還可以利用 binlog 數據,'復制'一個新的 mysql 出來。原來的 master 叫數據庫,復制出來的則是數據庫,主數據庫負責承接流量,從數據庫負責流量,這樣就可以讓 mysql 承接更高的讀寫流量。它就是經典的 mysql 主從同步架構

    數據庫查詢更新流程

    接下來我們用實際例子將上面提到的內容串起來。首先不管是查詢還是更新操作,客戶端都會先跟 mysql 建立網絡連接,并將 sql 發送到 server 層,經過分析器解析 sql 語法、優化器選擇索引生成執行計劃,最終給到執行器調用 InnoDB 的函數接口。

    • · 對于讀操作。InnoDB存儲引擎會先檢查 Buffer Pool 中是否存在所需的 B+樹數據頁,如果存在則直接返回數據。如果 Buffer Pool 中沒有所需的數據頁,則會從磁盤中讀取相應的數據頁加載到 Buffer Pool 中,再返回數據。同時,如果查詢的數據是熱點數據,還會將數據頁加入到自適應哈希索引豪華套餐中,加速后續的查詢。

    • · 對于寫操作,則會先將數據寫入 Buffer Pool,并生成相應的 Undo Log 記錄,以便在事務回滾時能夠恢復數據的原始狀態。接下來,會將寫操作記錄到 Redo Log Buffer 中,這些 redo log 會周期性地寫入到磁盤中的 Redo Log 文件中,就算數據庫崩了,已提交的事務也不會丟失。對于輔助索引的更新操作,InnoDB 會將這些更新暫時存儲在 Change Buffer 中,等到相關的索引頁被讀取到 Buffer Pool 時再進行實際的更新操作,從而減少磁盤 I/O,提高寫入性能。同時,所有的變更都會記錄到 server 層的 binlog 中,以便進行數據恢復。

    Image
    mysql架構總覽圖

    現在大家通了嗎?

    總結

    • · mysql 分為 server 層和存儲引擎層。存儲引擎層可更換,既可以是 myisam,也可以是 innodb。當前用 innodb 更多。

    • · innodb 分為內存和磁盤兩部分,一部分是內存里的自適應 hash,buffer bool,以及 redo log buffer。另一部分是磁盤里存放行數據和索引的.ibd 文件, 以及 undo log, redo log 等文件。

    • · mysql server 層會通過 binlog 記錄數據庫變更操作,binlog 可以用于數據恢復,也可以用于主從同步等場景。

    如果你覺得這篇文章對你有幫助,記得轉發給你那不成器的兄弟。最后遺留一個問題,你聽說過 HDFS 嗎?你知道它的架構是怎么樣的嗎?

    Image

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 精品人妻系列无码人妻漫画 | 亚洲精品综合网二三区| A毛片终身免费观看网站| 中文字字幕在线乱码视频| 又湿又紧又大又爽A视频国产| 96在线看片免费视频国产| 国产成AV人片久青草影院| 亚洲熟妇无码一区二区三区| 色窝窝免费播放视频在线| 强行无套内大学生初次| 国产精品无码免费播放| 嫩草成人AV影院在线观看| 国产A级作爱片无码| 国产成人无码A区在线观| 欧美又粗又大XXXXBBBB疯狂| 亚洲欧洲日产国无高清码图片| 人人妻人人澡人人爽欧美一区| 国产精品人妻中文字幕| 精品无码国产自产拍在线观看| 欧美肥老太牲交大战| 波多野结衣中文字幕一区二区三区| 办公室强奷漂亮少妇视频| 亚洲国产精品无码AAA片| 在线观看成人永久免费网站| 久久夜色精品国产嚕嚕亚洲AV| AV区无码字幕中文色| 色一情一乱一伦麻豆| 久久久久久亚洲精品成人| 亚洲欧美高清在线精品一区二区 | 国产福利一区二区三区在线观看| 亚洲国产精品一二三区| 亚洲精品无码久久久久去Q| 亚洲欧美自偷自拍视频图片| 久久婷婷五月综合97色直播| 中文无码久久精品| 久久无码中文字幕免费影院| 26uuu另类亚洲欧美日本| 国产无套粉嫩白浆在线观看| 夜夜爱夜鲁夜鲁很鲁| 中文字幕人妻在线精品| 日日摸夜夜添夜夜添高潮喷水|