文章目錄
- 1. MySQL 支持哪些存儲引擎?默認使?哪個?
- 2. MyISAM 和 InnoDB 有什么區別?
- 3. 事務的四大特性?
- 4. 并發事務帶來了哪些問題?
- 5. 不可重復讀和幻讀有什么區別?
- 6. MySQL 事務隔離級別?默認是什么級別?
- 7. MySQL 的隔離級別是基于鎖實現的嗎?
- 8. InnoDB 對 MVCC 的具體實現
- 9. char 和 varchar 的區別是什么?
- 10. varchar(100)和 varchar(10)的區別是什么?
- 11. decimal 和 float/double 的區別是什么?存儲?錢應該?哪?種?
- 12. 為什么索引能提高查詢速度?
- 13. 為什么MySQL不建議使用NULL作為列默認值?
- 14. 聚集索引和非聚集索引的區別?非聚集索引?定回表查詢嗎?
- 15. 索引這么多優點,為什么不對表中的每一個列創建一個索引呢?(使用索引一定能提高查詢性能嗎?)
- 16. 索引底層的數據結構了解嗎?Hash 索引和 B+樹索引優劣分析
- 17. B+樹做索引比紅黑樹好在哪里?
- 18. 最左前綴匹配原則了解嗎?
- 19. 什么是覆蓋索引?
- 20. 什么是回表?
- 21. 如何查看某條 SQL 語句是否用到了索引?
- 22. 表級鎖和行級鎖有什么區別?
- 23. 哪些操作會加表級鎖?哪些操作會加行級鎖?
- 24. MySQL中有哪些類型的鎖?
- 25. 當前讀和快照讀有什么區別?
- 26. 樂觀鎖和悲觀鎖是什么?
- 27. MySQL自增主鍵一定是連續的嗎?
- 28. MySQL 中常見的日志有哪些?
- 29. 數據庫的三大范式是什么
- 30. 慢查詢日志有什么用?
- 31. binlog 主要記錄了什么?
- 32. binlog 和 redolog 有什么區別?
- 33. redolog 什么情況下會出現數據丟失
- 34. 如何保證redolog 和 binlog的一致性
- 35. undo log 如何保證事務的原子性?
- 36. binlog 有哪幾種記錄格式
- 37. 如何進行SQL調優
- 38. 如何實現讀寫分離?
- 39. 什么是MySQL的主從同步機制
- 40. 什么是分庫分表
- 41. MySQL獲取數據,是從磁盤讀取的嗎?
- 42. 什么情況下,不推薦為數據庫建立索引?
- 43. 如何在MySQL中監控和優化慢SQL
內容參考:
https://javaguide.cn
、
https://t.zsxq.com/0bWeUrBVq
、
https://www.mianshiya.com
1. MySQL 支持哪些存儲引擎?默認使?哪個?
MySQL 5.5.5 之前,MyISAM 是 MySQL 的默認存儲引擎。5.5.5 版本之后,InnoDB 是 MySQL 的默認存儲引擎。
MySQL支持的存儲引擎中只有 InnoDB 是事務性存儲引擎,也就是說只有 InnoDB 支持事務。
2. MyISAM 和 InnoDB 有什么區別?
-
InnoDB 支持行級別的鎖粒度,MyISAM 不支持,只支持表級別的鎖粒度。
-
MyISAM 不提供事務支持。InnoDB 提供事務支持,實現了 SQL 標準定義了四個隔離級別。
-
MyISAM 不支持外鍵,而 InnoDB 支持。
-
MyISAM 不支持 MVCC,而InnoDB 支持。
-
雖然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree作為索引結構,但是兩者的實現方式不太一樣。
InnoDB 引擎中,其數據文件本身就是索引文件。相比 MyISAM,索引文件和數據文件是分離的,其表數據文件本身就是按 B+Tree 組織的一個索引結構,樹的葉節點 data 域保存了完整的數據記錄。
-
MyISAM 不支持數據庫異常崩潰后的安全恢復,而 InnoDB 支持。
-
InnoDB 的性能比MyISAM 更強大。
3. 事務的四大特性?
原子性(Atomicity)
:事務是最小的執行單位,不允許分割。事務的原子性確保動作要么全部完成,要么完全不起作用;一致性(Consistency)
:執行事務前后,數據保持一致,例如轉賬業務中,無論事務是否成功,轉賬者和收款人的總額應該是不變的;隔離性(Isolation)
:并發訪問數據庫時,一個用戶的事務不被其他事務所干擾,各并發事務之間數據庫是獨立的;持久性(Durability)
:一個事務被提交之后。它對數據庫中數據的改變是持久的,即使數據庫發生故障也不應該對其有任何影響。
只有保證了事務的持久性、原子性、隔離性之后,一致性才能得到保障。
4. 并發事務帶來了哪些問題?
1) 臟讀
事務A讀取了事務B??未提交??的修改,隨后事務B回滾,導致事務A讀到的數據是無效的(“臟數據”)。
2) 丟失修改
在一個事務讀取一個數據時,另外一個事務也訪問了該數據,那么在第一個事務中修改了這個數據后,第二個事務也修改了這個數據。這樣第一個事務內的修改結果就被丟失,因此稱為丟失修改。
3) 不可重復讀
事務A多次讀取同一數據,期間事務B??提交了修改??,導致事務A兩次讀取結果不一致(針對??已存在數據??的修改)。
4) 幻讀
幻讀與不可重復讀類似。它發生在一個事務讀取了幾行數據,接著另一個并發事務插入了一些數據時。在隨后的查詢中,第一個事務就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。
例如:事務 2 讀取某個范圍的數據,事務 1 在這個范圍插入了新的數據,事務 2 再次讀取這個范圍的數據發現相比于第一次讀取的結果多了新的數據。
5. 不可重復讀和幻讀有什么區別?
??對比維度?? ?? | 不可重復讀?? ?? | 幻讀 |
---|---|---|
??操作對象?? | 已存在的單行數據(值變化) | 滿足條件的多行數據(行數變化) |
??觸發操作?? | UPDATE、DELETE | INSERT、DELETE |
??表現形式 | ?? 同一行數據的值不同 | 結果集的行數不同 |
6. MySQL 事務隔離級別?默認是什么級別?
READ-UNCOMMITTED(讀取未提交)
:最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致臟讀、幻讀或不可重復讀。READ-COMMITTED(讀取已提交)
:允許讀取并發事務已經提交的數據,可以阻止臟讀,但是幻讀或不可重復讀仍有可能發生。REPEATABLE-READ(可重復讀)
默認
:對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發生。SERIALIZABLE(可串行化)
:最高的隔離級別,完全服從 ACID 的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。
隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |
7. MySQL 的隔離級別是基于鎖實現的嗎?
是基于鎖
和MVCC
共同實現的,MVCC主要是解決讀和寫兩種操作之間的沖突,提高并發事務的處理速度
寫與寫之間的沖突還是要加鎖來解決,只不過在不同的隔離級別下加的鎖不同
讀(普通的 select)和寫之間的沖突在RC和RR隔離級別下依靠MVCC快照讀
解決了
另一類 SELECT... FOR UPDATE
、SELECT ... LOCK IN SHARE MODE
在RU、RC會加行鎖,在RR、S隔離級別加臨鍵鎖(Next-Key Lock,行鎖 + 間隙鎖)??
SELECT... FOR UPDATE
的行鎖是X鎖,SELECT ... LOCK IN SHARE MODE
的行鎖是S鎖
這種是顯式上鎖的讀(主要目的是顯式上鎖),都是當前讀,UPDATE和DELETE都會隱式上鎖,那為啥有隱式上鎖還要有顯式上鎖呢?假設我們讀取賬號余額(必須保證讀取的數據是最新的,在扣減余額的時候不能被其他事務影響),如果沒有顯示上鎖,我們只能直接通過UPDATE/DELETE上鎖,但是我都不知道賬戶余額夠不夠扣減的,直接執行UPDATE肯定不行,如果沒有顯示上鎖,先通過普通select查詢余額,發現余額夠,然后去執行UPDATE,在這之間,余額被其他并發事務扣過一次了,結果當前事務在發現余額夠的情況下扣減余額成負的了,這顯然不合理
隔離級別 | 鎖的參與 | MVCC 的參與 | 解決的問題 |
---|---|---|---|
??讀未提交(RU) | ?? 寫操作加排他鎖,讀操作??無鎖?? | ? 不使用 | 無(臟讀、不可重復讀、幻讀) |
??讀已提交(RC)?? | 寫操作加排他鎖 | ? 每次 SELECT 生成新快照 | 臟讀 |
??可重復讀(RR)?? | 寫操作加排他鎖 + 間隙鎖 | ? 使用事務開始時的快照 | 臟讀、不可重復讀、幻讀(InnoDB) |
??串行化(S)?? | 所有操作加共享鎖/排他鎖 | ? 不使用 | 所有并發問題(但性能差) |
8. InnoDB 對 MVCC 的具體實現
InnoDB 的 MVCC 通過隱藏字段(事務ID和回滾指針)、Undo Log 版本鏈和 Read View 實現讀寫并發控制。在內部實現中,InnoDB 通過數據行的 事務ID
和 Read View
來判斷數據的可見性,如不可見,則通過數據行的 回滾指針
找到 undo log 中的歷史版本。每個事務讀到的數據版本可能是不一樣的,在同一個事務中,用戶只能看到該事務創建 Read View 之前已經提交的修改和該事務本身做的修改
9. char 和 varchar 的區別是什么?
主要區別:CHAR 是定長字符串,VARCHAR 是變長字符串。
CHAR 在存儲時會在右邊填充空格以達到指定的長度,檢索時會去掉空格;
VARCHAR 在存儲時需要使用 1 或 2 個額外字節記錄字符串的長度,檢索時不需要處理。
CHAR(M) 和 VARCHAR(M) 的 M 都代表能夠保存的字符數的最大值,
無論是字母、數字還是中文,每個都只占用一個字符。
10. varchar(100)和 varchar(10)的區別是什么?
VARCHAR(100)和 VARCHAR(10)都是變長類型,表示能存儲最多 100 個字符和 10 個字符。
VARCHAR(100)和 VARCHAR(10)能存儲的字符范圍不同,但二者存儲相同的字符串,所占用磁盤的存儲空間其實是一樣的。
不過,VARCHAR(100) 會消耗更多的內存。這是因為 VARCHAR 類型在內存中操作時,通常會分配固定大小的內存塊來保存值,即使用字符類型中定義的長度。
11. decimal 和 float/double 的區別是什么?存儲?錢應該?哪?種?
DECIMAL 是定點數,FLOAT/DOUBLE 是浮點數。DECIMAL 可以存儲精確的小數值,FLOAT/DOUBLE 只能存儲近似的小數值。
DECIMAL 用于存儲具有精度要求的小數,例如與貨幣相關的數據,可以避免浮點數帶來的精度損失。
12. 為什么索引能提高查詢速度?
??無索引時
??:數據庫需要逐行掃描整個表(全表掃描),時間復雜度為 O(n)。
有索引時??
:通過特定的數據結構(如 B+Tree)預先組織數據,查詢時只需掃描索引結構(如 B+Tree 的高度通常很小),時間復雜度降低到 O(log n)。幫助數據庫快速定位到目標數據的位置,避免全表掃描??。例如,2000 萬行數據的 B+Tree 索引可能只需 3-4 次磁盤 I/O 即可定位數據。
分析:每個數據頁16KB,假設是聚簇索引,key和指針占16B(非葉節點),key和數據占1KB(葉節點),一個三層的B+樹,可以存1000*1000*16條數據,定位這1600萬條數據只需要3次IO
13. 為什么MySQL不建議使用NULL作為列默認值?
- 唯一索引(UNIQUE)允許多個NULL值(除非顯式聲明NOT NULL),可能導致邏輯歧義。
- 索引中的NULL值會降低查詢效率。例如,WHERE column IS NULL可能無法有效利用索引,而NOT NULL列可通過索引直接定位數據。
- COUNT(column)會忽略NULL值,而COUNT(*)統計所有行。若列允許NULL,統計結果可能不符合預期。
- 在用=,!= 比較時,開發者需額外注意IS NULL/IS NOT NULL的用法,否則易引發邏輯錯誤。
14. 聚集索引和非聚集索引的區別?非聚集索引?定回表查詢嗎?
聚簇索引(聚集索引)
:索引結構和數據一起存放的索引,InnoDB 中的主鍵索引就屬于聚簇索引。
非聚簇索引(非聚集索引)
:索引結構和數據分開存放的索引,二級索引(輔助索引)就屬于非聚簇索引。二級索引的葉子節點存放的是主鍵,根據主鍵再回表查數據。
二級索引(輔助索引)屬于非聚簇索引。MySQL 的 MyISAM 引擎,不管主鍵還是非主鍵,使用的都是非聚簇索引。
非聚簇索引不一定回表查詢。如果要查詢的數據正好是非聚簇索引的key,就無需回表查詢。
聚簇索引和非聚簇索引的區別:
15. 索引這么多優點,為什么不對表中的每一個列創建一個索引呢?(使用索引一定能提高查詢性能嗎?)
大多數情況下,索引查詢都是比全表掃描要快的。但是如果數據庫的數據量不大,那么使用索引也不一定能夠帶來很大提升。因為:
- 創建和維護索引需要耗費許多時間。當對表中的數據進行增刪改的時候,如果數據有索引,那么索引也需要動態地修改,這會降低 SQL 執行效率。
- 索引需要使用物理文件存儲,也會耗費一定空間。
16. 索引底層的數據結構了解嗎?Hash 索引和 B+樹索引優劣分析
索引的底層數據結構通常有兩種常見實現:B+樹和哈希表。
B+樹是一種多路平衡查找樹,它的內部節點僅存儲鍵值和指向子節點的指針,而葉子節點存儲實際數據或指向數據的指針,葉子節點之間通過鏈表連接,這使得B+樹天然支持高效的范圍查詢和順序訪問。比如數據庫中的范圍查詢(如WHERE age > 20)或排序操作(ORDER BY)可以直接通過遍歷葉子節點的鏈表完成,同時B+樹的樹高較低,能減少磁盤I/O次數,非常適合磁盤存儲的場景,這也是為什么像MySQL的InnoDB引擎默認使用B+樹索引的原因。
而哈希索引基于哈希表實現,通過哈希函數將鍵值映射到固定桶中,理想情況下查詢時間復雜度為O(1),等值查詢(如WHERE id = 123)非常高效。但它不支持范圍查詢,因為數據是無序存儲的,例如WHERE age BETWEEN 10 AND 20需要全表掃描。
17. B+樹做索引比紅黑樹好在哪里?
B+樹通過多路平衡結構(每個節點可容納大量鍵值)大幅降低樹高,使得百萬級數據僅需3-4層即可覆蓋,顯著減少磁盤I/O次數;其葉子節點形成有序鏈表,使得范圍查詢無需回溯中間節點即可線性遍歷,而紅黑樹作為二叉樹在相同數據量下樹高更高且范圍查詢需復雜遍歷。同時,B+樹的節點大小與磁盤頁對齊,單次I/O能加載更多有效數據,且插入/刪除操作引發的節點分裂合并具有更好的局部性,減少了隨機磁盤訪問,而紅黑樹的旋轉操作可能導致分散的磁盤寫入(因為要修改父節點或者兄弟節點的指針,他們的數據可能存在不同的數據塊中,要分散讀取到內存中)。
18. 最左前綴匹配原則了解嗎?
最左前綴匹配原則指的是在使用聯合索引時,MySQL 會根據索引中的字段順序,從左到右依次匹配查詢條件中的字段。如果查詢條件與索引中的最左側字段相匹配,那么 MySQL 就會使用索引來過濾數據,這樣可以提高查詢效率。
最左匹配原則會一直向右匹配,直到遇到范圍查詢(如 >、<)為止。對于 >=、<=、BETWEEN 以及前綴匹配 LIKE 的范圍查詢,不會停止匹配
19. 什么是覆蓋索引?
如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為 覆蓋索引。覆蓋索引即需要查詢的字段正好是索引的字段,那么直接根據該索引,就可以查到數據了,而無需回表查詢。
20. 什么是回表?
在 InnoDB 存儲引擎中,非主鍵索引的葉子節點包含的是主鍵的值。這意味著,當使用非主鍵索引進行查詢時,數據庫會先找到對應的主鍵值,然后再通過主鍵索引來定位和檢索完整的行數據。這個過程被稱為“回表”。
21. 如何查看某條 SQL 語句是否用到了索引?
我們可以使用 EXPLAIN 命令來分析 SQL 的 執行計劃 ,這樣就知道語句是否命中索引了。執行計劃是指一條 SQL 語句在經過 MySQL 查詢優化器的優化會后,具體的執行方式。EXPLAIN 并不會真的去執行相關的語句,而是通過 查詢優化器 對語句進行分析,找出最優的查詢方案,并顯示對應的信息。
22. 表級鎖和行級鎖有什么區別?
表級鎖
: MySQL 中鎖定粒度最大的一種鎖(全局鎖除外),一般是用來針對非索引字段加的鎖,對當前操作的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。不過,觸發鎖沖突的概率最高,高并發下效率極低。表級鎖和存儲引擎無關,MyISAM 和 InnoDB 引擎都支持表級鎖。
行級鎖
: MySQL 中鎖定粒度最小的一種鎖,一般是針對索引字段加的鎖 ,只針對當前操作的行記錄進行加鎖。 行級鎖能大大減少數據庫操作的沖突。其加鎖粒度最小,并發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。行級鎖和存儲引擎有關,是在存儲引擎層面實現的。
23. 哪些操作會加表級鎖?哪些操作會加行級鎖?
表級鎖
:
- DDL 操作
修改表結構時(如 ALTER TABLE、DROP TABLE、TRUNCATE TABLE)會加表級鎖。 - 顯式鎖表
使用 LOCK TABLES 命令顯式鎖定表。 - MyISAM 引擎的讀寫
MyISAM 默認對寫操作加表級排他鎖,讀操作加表級共享鎖。 - 無索引的更新(InnoDB 鎖升級)
如果 UPDATE/DELETE 未使用索引,InnoDB 可能升級為表級鎖。
行級鎖
:
- 事務中的寫操作(InnoDB)
UPDATE、DELETE 默認對符合條件的行加排他鎖(X 鎖)。 - 顯式行級鎖查詢
SELECT … FOR UPDATE 加排他鎖,SELECT … LOCK IN SHARE MODE 加共享鎖。
24. MySQL中有哪些類型的鎖?
行級鎖
:僅對特定的行加鎖,允許其他事務并發訪問不同的行,適用于高并發場景。
表級鎖
:對整個表加鎖,其他事務無法對該表進行任何讀寫操作,適用于需要保證完整性的小型表。
共享鎖
:允許多個事務并發讀取同一資源,但不允許修改。只有在釋放共享鎖后,其他事務才能獲得排它鎖。
排他鎖
:只允許一個事務對資源進行讀寫,其他事務在獲得排它鎖之前無法訪問該資源。
間隙鎖
:針對索引中兩個記錄之間的間隙加鎖,防止其他事務在這個間隙中插入新記錄,以避免幻讀。間隙鎖不鎖定具體行,而是鎖定行與行之間的空間。
臨鍵鎖
:是行級鎖和間隙鎖的結合,鎖定具體行和其前面的間隙,確保在一個范圍內不會出現幻讀。常用于支持可重復讀的隔離級別。
意向鎖
:一種表鎖,用于表示某個事務對某行數據加鎖的意圖,分為意向共享鎖(IS)和意向排它鎖(IX),主要用于行級鎖與表級鎖的結合。
插入意向鎖
:一種特殊的間隙鎖(Gap Lock)??,允許不同事務在同一個間隙的不同位置并發插入數據??,從而減少鎖沖突。
25. 當前讀和快照讀有什么區別?
主要區別就是在于讀的時候鎖不鎖定
快照讀(一致性非鎖定讀)
就是普通的 SELECT 語句
只有在事務隔離級別 RC(讀取已提交) 和 RR(可重讀)下,InnoDB 才會使用一致性非鎖定讀:
- 在 RC 級別下,對于快照數據,一致性非鎖定讀總是讀取被鎖定行的最新一份快照數據。
- 在 RR 級別下,對于快照數據,一致性非鎖定讀總是讀取本事務開始時的行數據版本。
當前讀 (一致性鎖定讀)
就是給行記錄加 X 鎖或 S 鎖
# 對讀的記錄加一個X鎖
SELECT...FOR UPDATE
# 對讀的記錄加一個S鎖
SELECT...LOCK IN SHARE MODE#(舊版,已棄用)
# 對讀的記錄加一個S鎖
SELECT...FOR SHARE#(新版)
# 對修改的記錄加一個X鎖
INSERT...
UPDATE...
DELETE...
26. 樂觀鎖和悲觀鎖是什么?
悲觀鎖
:
假設并發沖突一定會發生,因此在操作數據前先加鎖,確保操作過程中數據不會被其他事務修改。
實現方式
- 數據庫內置鎖機制:如行鎖、表鎖、共享鎖(S鎖)、排他鎖(X鎖)。
樂觀鎖
假設并發沖突很少發生,因此不加鎖直接操作數據,僅在提交時檢查數據是否被修改。若沖突則重試或報錯。
實現方式
- 版本號機制:通過版本號或時間戳標記數據版本。
- CAS(Compare and Swap):原子操作更新數據前檢查當前值是否符合預期。
27. MySQL自增主鍵一定是連續的嗎?
詳細分析:https://javaguide.cn/database/mysql/mysql-auto-increment-primary-key-continuous.html
不一定,在以下情況可能不連續:
- 自增初始值和自增步長設置不為 1
- 唯一鍵沖突
- 事務回滾
- 批量插入(如 insert…select 語句)
28. MySQL 中常見的日志有哪些?
MySQL中常見的日志主要包括錯誤日志、通用查詢日志、慢查詢日志、二進制日志(Binlog)
、事務日志(Redo Log 和 Undo Log)
、中繼日志以及DDL日志。
二進制日志(Binlog)記錄了所有對數據的修改操作,支持主從復制和數據恢復,是實現高可用架構的基礎。
事務日志中的Redo Log確保事務的持久性,崩潰恢復時重放未落盤的操作,而Undo Log保存事務前的數據快照,支持回滾和MVCC機制。
29. 數據庫的三大范式是什么
- 1NF(第一范式):屬性不可再分。
- 2NF(第二范式):2NF 在 1NF 的基礎之上,消除了非主屬性對于碼的部分函數依賴。
- 3NF(第三范式):3NF 在 2NF 的基礎之上,消除了非主屬性對于碼的傳遞函數依賴 。
30. 慢查詢日志有什么用?
慢查詢日志主要是用來幫我們揪出數據庫里那些執行特別慢的SQL語句,比如有時候系統突然卡了或者用戶反饋頁面加載慢,這時候就可以去翻翻慢查詢日志,看看是不是哪條查詢拖了后腿。比如說,如果一條SQL執行了十幾秒甚至更久,它會被自動記錄到日志里,這樣我們就能快速定位到問題語句,而不是像大海撈針一樣去排查整個系統。
31. binlog 主要記錄了什么?
Binlog(二進制日志)可以理解為數據庫的“操作流水賬”,它主要記錄了MySQL服務器運行期間所有對數據庫結構或數據產生修改的操作,比如插入、更新、刪除這些寫動作。
這樣一來,binlog就有了兩個核心用途:一個是??主從復制??,從庫可以通過拉取主庫的binlog來逐條重放這些操作,保持數據同步;另一個是??數據恢復??,比如哪天誤刪了數據或者數據庫崩潰,可以通過binlog“回放”某個時間點之后的所有操作,把數據追到最新狀態。
32. binlog 和 redolog 有什么區別?
binlog主要用于數據庫還原,屬于數據級別的數據恢復,主從復制是binlog最常見的一個應用場景。redolog主要用于保證事務的持久性,屬于事務級別的數據恢復。
33. redolog 什么情況下會出現數據丟失
- redolog寫入log buffer但還未寫入page cache,此時數據庫崩潰,就會出現數據丟失;
- redolog已經寫入pagecache但還未寫入磁盤,操作系統奔潰,也可能出現數據丟失。
34. 如何保證redolog 和 binlog的一致性
InnoDB用??兩階段提交??來保證Redolog和Binlog的一致性。事務提交時,先寫Redolog到prepare狀態,再寫Binlog,最后把Redolog標記為commit。這樣如果中途崩潰,重啟時會檢查Binlog是否完整——如果Binlog有記錄,就說明事務應該提交,用Redolog恢復數據;如果Binlog沒記錄,就回滾事務。這樣避免了主從庫數據不一致或者恢復后數據錯亂的問題。
35. undo log 如何保證事務的原子性?
Undo log通過記錄事務執行前的數據狀態來確保原子性。在事務執行過程中,每一條修改數據的操作都會生成對應的undo log記錄,這些記錄保存了數據修改前的原始值。如果事務在執行期間遇到錯誤或被顯式回滾,數據庫系統會依據undo log中的逆向操作鏈條,逐條撤銷已完成的修改,將數據恢復到事務開始前的狀態。
36. binlog 有哪幾種記錄格式
statement
指定statement,記錄的內容是SQL語句原文。row
(5.7之后默認)
直接記錄數據變化mixed
對上述兩種方式的折中,默認情況下記錄SQL語句(STATEMENT模式),但當檢測到可能引發數據歧義的操作(如使用不確定函數或觸發器)時,自動切換為ROW格式記錄具體的數據變更。
37. 如何進行SQL調優
平時進行SQL調優,主要是通過觀察慢SQL,然后利用explain分析查詢語句的執行計劃,識別性能瓶頸,優化查詢語句。
- 合理設計索引,利用聯合索引進行覆蓋索引的優化,避免回表的發生,減少一次查詢和隨機I/O
- 避免SELECT*,只查詢必要的字段
- 避免在SQL中進行函數計算等操作,使得無法命中索引
- 避免使用LIKE %,導致全表掃描
- 注意聯合索引|需滿足最左匹配原則
- 不要對無索引字段進行排序操作
- 連表查詢需要注意不同字段的字符集是否一致,否則也會導致全表掃描
除此之外,還可以利用緩存來優化,一些變化少或者訪問頻繁的數據設置到緩存中,減輕數據庫的壓力,提升查詢的效率。
還可以通過業務來優化,例如少展示一些不必要的字段,減少多表查詢的情況,將列表查詢替換成分頁分批查詢等等。
38. 如何實現讀寫分離?
讀寫分離就是讀操作和寫操作從以前的一臺服務器上剝離開來,將主庫壓力分擔一些到從庫。本質上是因為訪問量太大,主庫的壓力過大,單機數據庫無法支撐并發讀寫。然后一般而言讀的次數遠高于寫,因此將讀操作分發到從庫上,這就是常見的讀寫分離。
讀寫分離時可以讓主庫不建查詢的索引,從庫建查詢的索引。
因為索引是需要維護的,比如你插入一條數據,不僅要在聚簇索引上面插入,對應的二級索引也得插入,修改也是一樣的。所以將讀操作分到從庫了之后,可以在主庫把查詢要用的索引刪了,減少寫操作對主庫的影響。
39. 什么是MySQL的主從同步機制
MySQL的主從同步機制是一種數據復制技術,用于將主數據庫(Master)上的數據同步到一個或多個從數據庫(Slave)中。
主要是通過二進制日志(BinaryLog,簡稱binlog)實現數據的復制。主數據庫在執行寫操作時,會將這些操作記錄到binlog中,然后推送給從數據庫,從數據庫重放對應的日志即可完成復制。
40. 什么是分庫分表
分庫分表是數據庫性能優化的一種方法,通過將數據分散存儲在多個數據庫或表中,來提高系統的可擴展性、性能和可用性。
分庫分表的類型(或策略)包括:
1)水平分表:
將同一張表的數據按行劃分,分散到多個表中。例如,可以按用戶ID的范圍將數據分為多個表(如user_1、user_2)。
2)垂直分表:
將一張表的不同列拆分到多個表中,以減少每張表的字段數量和提高查詢效率。例如,用戶表可以分為基本信息表和詳細信息表。
3)水平分庫:
將相同的表結構復制一份到另一個庫中,每個庫的表結構是一樣的,可以減少單一數據庫的讀寫壓力,在大數量的情況下提高讀寫性能。例如,database1、database2。
4)垂直分庫:
將數據分散到不同的數據庫實例中。可以根據業務功能或模塊進行分庫,如將用戶數據、訂單數據分別存儲在不同的數據庫中。
41. MySQL獲取數據,是從磁盤讀取的嗎?
在MySQL中,獲取數據并不總是直接從磁盤讀取。MySQL使用緩存機制,比如InnoDB存儲引擎,會將常用的數據和索引緩存在內存中,以提高讀取性能。當查詢數據時,系統首先會檢查緩存(如緩沖池),如果數據存在于內存中,則直接從內存中讀取;如果不在,則會從磁盤讀取并加載到緩存中。
42. 什么情況下,不推薦為數據庫建立索引?
1)對于數據量很小的表
當表的數據量很小(如幾百條記錄)時,建立索引并不會顯著提高查詢性能,反而可能增加管理的復雜性。
2)頻繁更新的表
對于頻繁進行插入、更新和刪除操作的表,索引會導致額外的維護開銷,因為每次數據變更時都需要更新索引,這會影響性能。
3)低選擇性字段(高度重復值的列)
當索引字段的取值重復度高(如性別字段“男”、“女”),索引的效果不明顯,且會增加存儲空間的浪費。
4) 長文本字段
會影響每個數據頁存放key的數量,導致B+樹變高,磁盤IO次數變多
43. 如何在MySQL中監控和優化慢SQL
可以利用MySQL自帶的slow_query_log來監控慢SQL,它是MySQL提供的一個日志功能,用于記錄執行時間超過特定閾值的SQL語句。
對于慢查詢,再使用EXPLAIN分析執行計劃,查看查詢的執行順序、使用的索引、掃描的行數等,以識別潛在的性能瓶頸。