「建議收藏」Mysql 知識乾貨(mysql 八股文)匯總

java江南 發佈 2022-05-23T20:02:36.970578+00:00

這一篇文章分享 mysql 的面試知識,涵蓋點比較多。下面我們來從總體到局部來看完 mysql 相關的面試知識。問:mysql 整體架構是怎麼樣的?mysql 整體架構大概可以分為:網絡連接層、服務層、存儲引擎層和系統文件層。

這一篇文章分享 MySQL 的面試知識,涵蓋點比較多。下面我們來從總體到局部來看完 mySQL 相關的面試知識。

問:mysql 整體架構是怎麼樣的?

mysql 整體架構大概可以分為:網絡連接層、服務層、存儲引擎層和系統文件層。

關於 mysql 官方的架構圖如下,雖然經歷多個版本疊代,但整體架構還是差不多,mysql 官方地址如下:https://docs.oracle.com/cd/E19078-01/mysql/mysql-refman-5.1/storage-engines.html#figure-storage-engine-architecture:


1)網絡連接層

Connectors 組件,是 mysql 向外提供的交互組件,如 java,.net,php 等語言可以通過該組件來操作 SQL 語句,實現與 SQL 的交互。

2)服務層

服務層是 mysql Server 的核心。主要包含系統管理和控制工具、連接池、SQL 接口、解析器、查詢優化器和緩存 Cache&Buffer 六個部分。

連接池(Connection Pool):負責存儲和管理客戶端與資料庫的連接,一個線程負責管理一個連接。

系統管理和控制工具(Management Services & Utilities):例如備份恢復、安全管理、集群 管理等

SQL 接口(SQL Interface):用於接受客戶端發送的各種 SQL 命令,並且返回用戶需要查詢的結果。

解析器(Parser):負責將請求的 SQL 解析生成一個"解析樹"。然後根據一些 mysql 規則進一步檢查解析樹是否合法。

查詢優化器(Optimizer):當「解析樹」通過解析器語法檢查後,將交由優化器將其轉化成執行計劃,然後與存儲引擎交互。

緩存(Cache&Buffer):緩存機制是由一系列小緩存組成的。比如表緩存,記錄緩存,權限緩存,引擎緩存等。如果查詢緩存有命中的查詢結果,查詢語句就可以直接去查詢緩存中取數據。

3)存儲引擎層(Pluggable Storage Engines)

存儲引擎負責 MySQL 中數據的存儲與提取,與底層系統文件進行交互。MySQL 存儲引擎是插件式的,伺服器中的查詢執行引擎通過接口與存儲引擎進行通信,接口屏蔽了不同存儲引擎之間的差異 。現在有很多種存儲引擎,各有各的特點,最常見的是 myisam 和 innodb。

4)系統文件層(File System)

該層負責將資料庫的數據和日誌存儲在文件系統之上,並完成與存儲引擎的交互,是文件的物理存儲層。主要包含日誌文件,數據文件,配置文件,pid 文件,socket 文件等。

問:mysql 集群架構

關於 mysql 的架構,最底層的只有主從模式,關於主從模式是簡單靈活,能滿足多種需求,比較主流的用法,但是寫操作高可用需要自己考慮。我們常見還有雙主模式,該模式從主從模式演變為雙主模式,有雙主雙寫、雙主單寫兩種方式,一般建議使用雙主單寫。關於主從架構的模式參考下面的圖。

問:MySQL 的查詢和插入的執行流程

下面我們圖解 mysql 一條查詢語句是怎麼運行的:


mysql 客戶端對 mysql server 的監聽埠發起請求

在連接池組件創建連接,分配線程,並驗證用戶名,密碼,庫表>權限。

查詢 query_cache,如果有數據直接返回,沒有則繼續執行。

通過 sql 接口組件接收 sql 語句,sql 會通過查詢分析器分解成數據結構,並且這個結構傳遞給後續步驟

查詢優化器組件組成查詢路徑樹,並選舉一條最優的查詢路徑。

調用存儲引擎接口,打開表,執行查詢,檢查存儲引擎緩存中是否有對應的緩存記錄,如果沒有就繼續往下執行。

到磁碟物理文件中尋找數據。

當查詢到所需要的數據之後,先寫入存儲引擎緩存中,並往 query_cache 寫進去。

返回數據給客戶端。

關閉表。

關閉線程。

關閉連接。

mysql 插入的過程如下


mysql 客戶端對 mysql server 的監聽埠發起請求

在連接池組件創建連接,分配線程,並驗證用戶名,密碼,庫表>權限。

檢查沒有問題之後,便進入引擎層開始正式的提交。我們知道 InnoDB 會將數據頁緩存至內存中的 buffer pool,所以 insert 語句到了這裡並不需要立刻將數據寫入磁碟文件中,只需要修改 buffer pool 當中對應的數據頁就可以了。

在開啟 redo log 刷盤策略的時候,當 innodb_flush_log_at_trx_commit=1 時,每次事務提交都會觸發一次 redo log 刷盤。(redo log 是順序寫入,相比直接修改數據文件,redo 的磁碟寫入效率更加高效)

如果開啟了 binlog 日誌,我們還需將事務邏輯數據寫入 binlog 文件,且為了保證複製安全,建議使用 sync_binlog=1 ,也就是每次事務提交時,都要將 binlog 日誌的變更刷入磁碟。

返回數據給客戶端。

關閉表。

關閉線程。

關閉連接。

問:mysql 有哪些欄位類型

關於 mysql 的數據類型主要以上幾種,一般我們創建表結構都是使用 innodb 引擎,後面我們會深入 innodb 引擎的知識。特別我們需要注意的是,為了獲取更好的兼容性,建議使用 utf8mb4 字符集,主要是用來兼容四字節的 unicode。

utf8mb4 與 utf8 的區別

mysql 在 5.5.3 版本之後增加了 utf8mb4 編碼,mb4 就是 most bytes 4 的意思,專門用來兼容四字節的 unicode。其實,utf8mb4 是 utf8 的超集,理論上原來使用 utf8,然後將字符集修改為 utf8mb4,也不會對已有的 utf8 編碼讀取產生任何問題。mysql 支持的 utf8 編碼最大字符長度為 3 字節,如果遇到 4 字節的寬字符就插入異常。

char 和 varchar 區別

char 表示定長,長度固定,varchar 表示變長,即長度可變。char 如果插入的長度小於定義長度時,則用空格填充;varchar 小於定義長度時,還是按實際長度存儲,插入多長就存多長。

char 的存取速度還是要比 varchar 要快得多,方便程序的存儲與查找;但是 char 也為此付出的是空間的代價,因為其長度固定,所以會占據多餘的空間,可謂是以空間換取時間效率。varchar 則剛好相反,以時間換空間。

對 char 來說,最多能存放的字符個數 255,和編碼無關。而 varchar 呢,最多能存放 65532 個字符。varchar 的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65,532 字節。

timestamp 和 datatime 區別

timestamp 占 4 個字節。datetime 占用 8 個字節

timestamp 記錄是 1970-01-01 00:00:01 到現在的數數,時間範圍:『1970-01-01 00:00:01』 UTC ~ 『2038-01-19 03:14:07』 UTC,受時區影響。datetime 不受時區影響,時間範圍:『1000-01-01 00:00:00』 ~ 『9999-12-31 23:59:59』

timestamp 存儲占用的空間和 INT 類型相同,客戶端插入的時間從當前時區轉化為 UTC,查詢時,將其又轉化為客戶端當前時區進行返回。datetime,不做任何改變,基本上是原樣輸入和輸出。

資料庫三範式

第一範式(1NF)是指資料庫表的每一列都是不可分割的基本數據線;也就是說:每列的值具有原子性,不可再分割。

第二範式(2NF)是在第一範式(1NF)的基礎上建立起來得,滿足第二範式(2NF)必須先滿足第一範式(1NF)。如果表是單主鍵,那麼主鍵以外的列必須完全依賴於主鍵;如果表是複合主鍵,那麼主鍵以外的列必須完全依賴於主鍵,不能僅依賴主鍵的一部分。

第三範式(3NF)是在第二範式的基礎上建立起來的,即滿足第三範式必須要先滿足第二範式。第三範式(3NF)要求:表中的非主鍵列必須和主鍵直接相關而不能間接相關;也就是說:非主鍵列之間不能相關依賴。在規範和性能之間需要平衡,如何表拆得過細,會導致查表關聯過多,導致性能問題。因此需要在規範性和性能之間作取捨。有時候會採用反三範式。

問:mysql 存儲引擎有哪些?innodb 有什麼特點?

innodb,myisam,memory,merge,archive,ndb

innodb 引擎,從 MySQL5.5 版本之後,MySQL 的默認內置存儲引擎已經是 innodb 了

支持事務,默認的事務隔離級別是可重複度,通過 MVCC(並發版本控制)來實現。

行級鎖,可以支持更高的並發。

支持外鍵,雖然有這個功能,但實際業務中不怎麼用。

在 innodb 中有緩衝管理,通過緩衝池,將索引和數據全部緩存起來,加速查詢速度。

在 innodb 中數據的物理組織形式是聚簇表。所有的數據按照主鍵來組織。數據和索引放在一塊,都位於 B+數的葉子節點上。

innodb 引擎如果沒有設置主鍵索引,innodb 則會選擇內置的 6 字節的 row-id 作為隱含的聚集索引。

innodb 支持分區,表空間。

innodb 引擎對硬體要求比較高。

innodb 災難恢復性比較好。

問:mysql 索引有哪些,特徵是怎麼樣的?

什麼是索引?

索引是幫助存儲引擎高效獲取數據的一種數據結構。

索引按照物理存儲的類型分聚簇索引,輔助索引

索引按照欄位特性分類:主鍵索引,唯一索引,普通索引,前綴索引,組合索引,全文索引(mysql5.6.4 之後支持)

優點:<br/>1)檢索:可以提高數據檢索的效率,降低資料庫的 IO 成本,2)排序:通過索引列對數據進行排序,降低了 CPU 的消耗

缺點:<br/>1)占磁碟空間,2)降低更新表的效率

下面我們看下不同的索引的含義和解釋

聚簇索引:主鍵索引(聚集索引)的葉子結點會存儲數據行,也就是說數據和索引在一起

輔助索引:同樣用 B+Tree,data 域存儲相應記錄主鍵的值而不是地址,首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。

覆蓋索引:覆蓋索引一般針對的是輔助索引,整個査詢結果只通過輔助索引就能拿到結果,不需要通過輔助索引樹找到主鍵,再通過主鍵去主鍵索引樹里獲取其它欄位值。

主鍵索引:主鍵索引是一種特殊的唯一索引,一個表只能有一個主鍵且不允許有空值;索引列只能出現一次且必須唯一,InnoDB 要求表必須有主鍵,如果沒有顯示設置主鍵索引,那麼會自動為數據表創建一個隱含的欄位 row-id 作為主鍵,這個欄位為 6 字節的長整型。

唯一索引:建立在 unique 欄位上的索引就是唯一索引,不允許具有索引值相同的行,索引列的值可以允許為 null

普通索引:要求欄位不為主鍵也不要求欄位為 unique 的索引叫普通索引。

前綴索引:前綴索引是指對字符類型欄位的前幾個字符或對二進位類型欄位的前幾個 bytes 建立的索引。例子:name(varchar(16))

組合索引:在表中的對個欄位組合上創建的索引。並且遵循最左前綴原則匹配。

全文索引:只能在 char,varchar,text 類型欄位上使用全文索引。全文索引,通過建立倒排索引,可以極大的提升檢索效率,解決判斷欄位是否包含的問題。

問:講講 mysql 事務?

事務:事務是邏輯上的一組操作,要麼都執行,要麼都不執行。

事務的特性:

原子性(atomicity):事務是最小的執行單位,不允許分割。事務的原子性確保動作要麼全部完成,要麼完全不起作用。

一致性(consistency):執行事務前後,數據保持一致,例如轉帳業務中,無論事務是否成功,轉帳者和收款人的總額應該是不變的。

隔離性(ioslation): 並發訪問資料庫時,一個用戶的事務不被其他事務所干擾,各並發事務之間資料庫是獨立的。

持久性(durability):一個事務被提交之後,對資料庫中數據的改變是持久的,即使資料庫發生故障也不應該對其有任何影響。

事務的隔離級別

讀取未提交 READ-UNCOMMITTED

允許讀取尚未提交的數據變更,最低的隔離級別,可能導致髒讀幻讀不可重複讀

讀取已提交 READ-COMMITTED

允許讀取並發事務已經提交的數據,可以避免髒讀,可能導致幻讀或不可重複讀。

可重複讀 REPEATABLE-READ

同一個事務下多次讀取結果都是一致的,除非數據是被自己的事務所修改,可以避免髒讀、不可重複讀,但可能導致幻讀。

串行化 SERIALIZABLE

髒讀(讀取未提交數據):

髒讀指的是讀到了其他事務未提交的數據,未提交意味著這些數據可能會回滾,也就是可能最終不會存到資料庫中,也就是不存在的數據。讀到了並一定最終存在的數據,這就是髒讀

不可重複讀(前後多次讀取,數據內容不一致):

一個事務內兩個相同的查詢卻返回了不同數據。這是由於查詢時系統中其他事務修改的提交而引起的。

幻讀(前後多次讀取,數據總量不一致):

一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,另一個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,操作前一個事務的用戶會發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。

mysql 創建事務方式

START TARNSACTION |BEGIN:顯式地開啟一個事務。 COMMIT:提交事務,使得對資料庫做的所有修改成為永久性。 ROLLBACK:回滾會結束用戶的事務,並撤銷正在進行的所有未提交的修改。

mysql 默認的事務隔離級別是:可重複讀

問:講講 mysql 鎖相關知識

mysql 的鎖按照範圍可以分為全局鎖、表鎖、行鎖,其中行鎖是由資料庫引擎實現的,並不是所有的引擎都提供行鎖。我這裡只講 innodb 引擎的鎖。

全局鎖

mysql 提供全局鎖來對整個資料庫實例加鎖。

// 鎖表 FLUSH TABLES WITH READ LOCK // 解鎖 unlock tables

上面語句一般都是用來備份的,當執行這條語句後,資料庫所有打開的表都會被關閉,並且使用全局讀鎖鎖定資料庫的所有表,同時,其他線程的更新語句(增刪改),數據定義語句(建表,修改表結構)和更新類的事務提交都會被阻塞。

mysql 8.0 以後,對於備份,mysql 可以直接使用備份鎖

// 加鎖 LOCK INSTANCE FOR BACKUP // 解鎖 UNLOCK INSTANCE

備份鎖範圍更廣,會阻止文件的創建,重命名,刪除,包括 REPAIR TABLE TRUNCATE TABLE, OPTIMIZE TABLE 操作以及帳戶的管理都會被阻塞。當然這些操作對於內存臨時表來說是可以執行的,為什麼內存表不受這些限制呢?因為內存表不需要備份,所以也就沒必要滿足這些條件。

表鎖

表級別鎖分為兩類,一類是元數據鎖(Metadata Lock,MDL),一種是表鎖。

表鎖分為讀鎖和寫鎖,讀鎖不互斥,但是獲取讀鎖不能寫入數據,其他沒有獲取到讀鎖的 session 也是可以讀取表的,所以讀鎖的目的就是限制表被寫。

寫鎖被獲取後可以對表進行讀寫,寫鎖是互斥的,一旦某個 session 獲取到表的寫鎖,另外的 session 無法訪問這個表,直到寫鎖被釋放。

表的解鎖可以使用 unlock tables 解鎖,也可以客戶埠自動解鎖。

元數據鎖(MDL) 不需要顯式使用,在訪問一個表的時候會被自動加上。這個特性需要 MySQL5.5 版本以上才會支持,當對一個表做增刪改查的時候,該表會被加 MDL 讀鎖;當對表做結構變更的時候,加 MDL 寫鎖。

MDL 鎖有一些規則

讀鎖之間不互斥,所以可以多線程多同一張表進行增刪改查。

讀寫鎖、寫鎖之間是互斥的,為了保證表結構變更的安全性,所以如果要多線程對同一個表加欄位等表結構操作,就會變成串行化,需要進行鎖等待。

MDL 的寫鎖優先級比 MDL 讀鎖的優先級高,但是可以設置 max_write_lock_count 系統變量來改變這種情況,當寫鎖請求超過這個變量設置的數後,MDL 讀鎖的優先級會比 MDL 寫鎖的優先級高。(默認情況下,這個數字會很大,所以不用擔心寫鎖的優先級下降)

MDL 的鎖釋放必須要等到事務結束才會釋放

行鎖

共享鎖

共享鎖能允許事務獲取到鎖後進行讀操作,共享鎖是不互斥的,一個事務獲取到共享鎖後,另外一個事務也可以獲取共享鎖,獲取共享鎖後不能進行寫操作

排它鎖

排他鎖允許事務獲取到鎖後進行更新一行或者刪除某一行操作,排他鎖顧名思義是互斥的,一個事務獲取到排他鎖後,其他事務不能獲取到排他鎖,直到這個鎖被釋放。

意向鎖

innodb 支持多種粒度的鎖,允許行鎖和表鎖共存,這裡說的意向鎖其實是一種表級別的鎖,但是我把它放在行鎖裡面是因為它不會單獨存在,它的出現肯定會伴隨著行鎖(共享鎖或者排他鎖),它主要的目的就是表示將要鎖定表中的行或者正在鎖定表中的行。意向鎖的獲取必須在行鎖獲取之前,也就是說獲取共享鎖之前必須先要獲取共享意向鎖,對於排他鎖也是一樣的道理。

死鎖<DeadLock>

是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。表級鎖不會產生死鎖.所以解決死鎖主要還是針對於最常用的 innodb。

問:講講 mysql mvcc 的機制

多版本並發控制技術的英文全稱是 Multiversion Concurrency Control,簡稱 MVCC。

多版本並發控制(MVCC) 是通過保存數據在某個時間點的快照來實現並發控制的。也就是說,不管事務執行多長時間,事務內部看到的數據是不受其它事務影響的,根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的數據可能是不一樣的。

多版本並發控制的思想是保存數據的歷史版本,通過對數據行的多個版本管理來實現資料庫的並發控制。這樣我們就可以通過比較版本號決定數據是否顯示出來,讀取數據的時候不需要加鎖也可以保證事務的隔離效果。

MVCC 解決了哪些問題?

讀寫之間阻塞的問題。通過 MVCC 可以讓讀寫互相不阻塞,即讀不阻塞寫,寫不阻塞讀,這樣就可以提升事務並發處理能力。

降低了死鎖的概率。因為 InnoDB 的 MVCC 採用了樂觀鎖的方式,讀取數據時並不需要加鎖,對於寫操作,也只鎖定必要的行。

解決一致性讀的問題。一致性讀也被稱為快照讀,當我們查詢資料庫在某個時間點的快照時,只能看到這個時間點之前事務提交更新的結果,而不能看到這個時間點之後事務提交的更新結果。快照讀(SnapShot Read) 是一種一致性不加鎖的讀,是 InnoDB 並發如此之高的核心原因之一。

innodb 的 MVCC 是如何工作的?

事務版本號:每開啟一個事務,我們都會從資料庫中獲得一個事務 ID(也就是事務版本號),這個事務 ID 是自增長的,通過 ID 大小,我們就可以判斷事務的時間順序。

行記錄的隱藏列:innodb 的葉子段存儲了數據頁,數據頁中保存了行記錄,而在行記錄中有一些重要的隱藏欄位:

DB_TRX_ID(6 字節): 它是最近一次更新或者插入或者刪除該行數據的事務 ID(若是刪除,則該行有一個刪除位更新為已刪除。但並不是真正的進行物理刪除,當 InnoDB 丟棄為刪除而編寫的更新撤消日誌記錄時,它才會物理刪除相應的行及其索引記錄。此刪除操作稱為清除,速度非常快)

DB_ROLL_PTR(7 字節): 回滾指針,指向當前記錄行的 undo log 信息(指向該數據的前一個版本數據)

DB_ROW_ID(6 字節): 隨著新行插入而單調遞增的行 ID。InnoDB 使用聚集索引,數據存儲是以聚集索引欄位的大小順序進行存儲的,當表沒有主鍵或唯一非空索引時,innodb 就會使用這個行 ID 自動產生聚簇索引。如果表有主鍵或唯一非空索引,聚簇索引就不會包含這個行 ID 了。這個 DB_ROW_ID 跟 MVCC 關係不大。

undo log 將行記錄快照保存在裡面,我們可以在回滾段中找到它們。

在可重複讀的隔離級別下:

查詢:符合下面兩個條件的記錄作為返回結果:1)innodb 只查找版本早於當前事務版本的數據行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務自身插入或者修改過的。2)行的刪除版本要麼未定義,要麼大於當前事務版本號。這可以確保事務讀取到的行,在事務開始之前未被刪除。

插入:innodb 為新插入的每一行保存當前系統版本號作為行版本號。

刪除:innodb 為刪除的每一行保存當前系統版本號作為行刪除標識。刪除在內部被視為更新,行中的一個特殊位會被設置為已刪除。

更新:innodb 為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。

問:講講的 mysql 主從複製

什麼是主從複製?

mysql 主從複製是指數據可以從一個 mysql 資料庫伺服器主節點複製到一個或者多個從節點。mysql 默認使用異步複製方式,這樣從節點不用一直訪問主伺服器來更新自己的數據,數據的更新可以在遠程連接上進行,從節點可以複製主資料庫中的所有資料庫或者特定的資料庫,或者特定的表。

主從複製實現原理

master 伺服器將數據的改變記錄二進位 binlog 日誌,當 master 上的數據發生改變時,則將其改變寫入二進位日誌中。

slave 伺服器會在一定時間間隔內對 master 二進位日誌進行探測其是否發生改變,如果發生改變,則開始一個 I/OThread 請求 master 二進位事件。

同時主節點為每個 I/O 線程啟動一個 dump 線程,用於向其發送二進位事件,並保存至從節點本地的中繼日誌中,從節點將啟動 SQL 線程從中繼日誌中讀取二進位日誌,在本地解析執行,使得其數據和主節點的保持一致,最後 I/OThread 和 SQLThread 將進入睡眠狀態,等待下一次被喚醒。

基於 gtid 的複製模式

什麼是 gitd?

gtid(Global Transaction ID)對於一個已提交事務的編號,並且是一個全局唯一的編號。GTID 實際上 是由 UUID+TID 組成的。其中 UUID 是一個 mysql 實例的唯一標識。TID 代表了該實例上已經提交的事務數量,並且隨著事務提交單調遞增。

gtid 的複製原理

當一個事務在主庫端執行並提交時,產生 gtid,一同記錄到 binlog 日誌中。

binlog 傳輸到 slave,並存儲到 slave 的 relaylog 後,讀取這個 gtid 的這個值設置 gtid_next 變量,即告訴 Slave,下一個要執行的 gtid 值。

sql 線程從 relay log 中獲取 gtid,然後對比 slave 端的 binlog 是否有該 gtid。

如果有記錄,說明該 gtid 的事務已經執行,slave 會忽略。

如果沒有記錄,slave 就會執行該 gtid 事務,並記錄該 gtid 到自身的 binlog,在讀取執行事務前會先檢查其他 session 持有該 gtid,確保不被重複執行。

在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果沒有就用全部掃描。

問:mysql 如何保證寫入數據不丟失?

總結:保證 redo log 和 bin log 可以持久化到磁碟,並且確保 mysql 在異常重啟後進行數據恢復。

bin log 的寫入機制:

事務執行過程中,先把日誌寫到 binlog cache(內存)

事務提交的時候(mysql 客戶端執行 commit 指令),再把 bin log cache 中寫到 bin log 文件中,並清空 bin log cache

每個線程都有自己的一個 bin log cache,但是共同使用同一份 bin log

write 把 binlog cache 寫入到文件系統的 page cache,不會真正將數據持久化到磁碟。

fsync 才是將數據持久化到磁碟(此時會占用磁碟的 IOPS)

redo log 的寫入機制:

事務在執行過程中,生成的 redo log 首先會寫到 redo log buffer

redo log 會在一些特定條件下寫入日誌文件

write 到磁碟(存儲在 Page Cache 中),此時沒有實際調用 fsync 寫入磁碟

持久化到磁碟,調用了 fsync

問:mysql 的 MRR 是什麼?

MRR,全稱「Multi-Range Read Optimization」。

官方說法:MRR 通過把「隨機磁碟讀」,轉化為「順序磁碟讀」,從而提高了索引查詢的性能。

其實 MRR 是基於索引的查詢做的一個優化,對於 innodb,則會按照聚簇索引鍵值排好序,在內存上索引和磁碟上的索引存儲也是有序的,通過順序的讀取聚簇索引。索引本身就是為了減少磁碟 IO,加快查詢,而 MRR,則是把索引減少磁碟 IO 的作用,MRR 在本質上是一種用空間換時間的算法。

問:講講 mysql 如何分庫分表?

分庫分表主要解決 IO 瓶頸,CPU 瓶頸。

分庫分表:水平分庫分表,垂直分庫分表等

具體分庫分表的方式經驗是:日誌類的拆分策略是按照日期,另外拆分策略就是 hash 法。


小夥伴們有興趣想了解內容和更多相關學習資料的請點讚收藏+評論轉發+關注我,後面會有很多乾貨。我有一些面試題、架構、設計類資料可以說是程式設計師面試必備!所有資料都整理到網盤了,需要的話歡迎下載!私信我回復【111】即可免費獲取
















































































作者:【利志分享】

出處:https://xie.infoq.cn/article/1c7a6f28f2b02819ee1674950

關鍵字: