在之前好多章節(jié)中,已經(jīng)把語言類和計算機網(wǎng)絡做了相關總結(jié),后面我會專門出一章來總結(jié)一下之前的筆記,給大家捋一捋到底該怎么去看這些文章。
雖然這會兒總結(jié)出來的都是很零散的知識,可能看的時候沒有什么頭緒,也不知道從什么地方看起,但是你也可以去合集找找相關的專題,都很全,文章字數(shù)可能有點多,學習的時候還是需要點耐心的哈。
作為后端開發(fā)工程師,數(shù)據(jù)庫是怎么也繞不過去的一個坎,相信你們在學校的時候也學過什么SQLserver或者其它數(shù)據(jù)庫,最多的可能就是練習寫寫SQL語句類的東西。
MySQL作為當下最流行的關系型數(shù)據(jù)庫之一,也是面試中的“熱門”,面試官不僅會考察你對SQL語句的熟練程度,也會對它的一個底層原理做非常多的考察。只要你簡歷上寫就必問,要是沒寫,也會問你會不會數(shù)據(jù)庫。所以你自己體會它的重要性。
今天這節(jié)內(nèi)容是對MySQL數(shù)據(jù)庫在面試過程中遇到的一些高頻問題做一個總結(jié),可能你看完這篇文章就不需要專門去準備數(shù)據(jù)庫相關的知識了。里面的內(nèi)容大多是我在面試過程中遇到的,大家都知道近兩年是非常非常卷的,一個崗位可能有無數(shù)個候選人在面試,如果你想脫穎而出,那么就需要非常強的基礎作為你的踏板。OK,不浪費時間說這么多了,大家認真看吧。
一、數(shù)據(jù)庫基礎
1、數(shù)據(jù)庫索引為什么要B+樹
數(shù)據(jù)庫的索引是使用B+樹來實現(xiàn)的。
那為什么要用B+樹,為什么不用紅黑樹和B樹?
B+樹是一種特殊的平衡多路樹,是B樹的優(yōu)化改進版本,它把所有的數(shù)據(jù)都存放在葉節(jié)點上,中間節(jié)點保存的是索引。這樣一來相對于B樹來說,減少了數(shù)據(jù)對中間節(jié)點的空間占用,使得中間節(jié)點可以存放更多的指針,使得樹變得更矮,深度更小,從而減少查詢的磁盤IO次數(shù),提高查詢效率。另一個是由于葉節(jié)點之間有指針連接,所以可以進行范圍查詢,方便區(qū)間訪問。
而紅黑樹是二叉的,它的深度相對B+樹來說更大,更大的深度意味著查找次數(shù)更多,更頻繁的磁盤IO,所以紅黑樹更適合在內(nèi)存中進行查找。
B+樹更適合操作系統(tǒng)文件索引和數(shù)據(jù)索引的原因:
- B+樹磁盤讀寫代價更低,B+樹的內(nèi)部節(jié)點沒有指向關鍵字具體信息的指針。因此內(nèi)部節(jié)點相對于B-樹更小,如果把所有同一內(nèi)部節(jié)點的關鍵字放入同一塊磁盤當中。盤所能容納的關鍵字數(shù)量也就更多。一次性讀入內(nèi)存中需要查找的關鍵字也就越多,相對的IO讀寫次數(shù)就有所降低。
- B+樹查詢效率更加穩(wěn)定。由于非終結(jié)點并不是最終指向文件內(nèi)容的節(jié)點,而只是葉子節(jié)點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根節(jié)點到葉子節(jié)點的路徑。所有的關鍵字查詢路徑長度都是相同的,導致了每一個數(shù)據(jù)查詢的效率相當。
2、MYSQL的引擎對比
2.1、MySQL引擎
MySQL中的數(shù)據(jù)用各種不同的技術存儲在文件(或者內(nèi)存)中。這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平并且最終提供廣泛的不同的功能和能力。通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能。
數(shù)據(jù)庫引擎是用于存儲、處理和保護數(shù)據(jù)的核心服務。利用數(shù)據(jù)庫引擎可控制訪問權限并快速處理事務,從而滿足企業(yè)內(nèi)大多數(shù)需要處理大量數(shù)據(jù)的應用程序的要求。使用數(shù)據(jù)庫引擎創(chuàng)建用于聯(lián)機事務處理或聯(lián)機分析處理數(shù)據(jù)的關系數(shù)據(jù)庫。這包括創(chuàng)建用于存儲數(shù)據(jù)的表和用于查看、管理和保護數(shù)據(jù)安全的數(shù)據(jù)庫對象(如索引、視圖和存儲過程)。
MySQL存儲引擎主要有:MyIsam、InnoDB、Memory、Blackhole、CSV、Performance_Schema、Archive、Federated、Mrg_Myisam。
但是最常用的是InnoDB和Mylsam。
2.2、InnoDB
InnoDB是一個事務型的存儲引擎,有行級鎖定和外鍵約束。
Innodb引擎提供了對數(shù)據(jù)庫ACID事務的支持,并且實現(xiàn)了SQL標準的四種隔離級別,關于數(shù)據(jù)庫事務與其隔離級別的內(nèi)容請見數(shù)據(jù)庫事務與其隔離級別這類型的文章。該引擎還提供了行級鎖和外鍵約束,它的設計目標是處理大容量數(shù)據(jù)庫系統(tǒng),它本身其實就是基于MySQL后臺的完整數(shù)據(jù)庫系統(tǒng),MySQL運行時Innodb會在內(nèi)存中建立緩沖池,用于緩沖數(shù)據(jù)和索引。但是該引擎不支持FULLTEXT類型的索引,而且它沒有保存表的行數(shù),當SELECT COUNT(*) FROM TABLE時需要掃描全表。當需要使用數(shù)據(jù)
庫事務時,該引擎當然是首選。由于鎖的粒度更小,寫操作不會鎖定全表,所以在并發(fā)較高時,使用Innodb引擎會提升效率。但是使用行級鎖也不是絕對的,如果在執(zhí)行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表。
適用場景:
- 經(jīng)常更新的表,適合處理多重并發(fā)的更新請求。
- 支持事務。
- 可以從災難中恢復(通過bin-log日志等)。
- 外鍵約束。只有他支持外鍵。
- 支持自動增加列屬性auto_increment。
索引結(jié)構:
- InnoDB也是B+Treee索引結(jié)構。Innodb的索引文件本身就是數(shù)據(jù)文件,即B+Tree的數(shù)據(jù)域存儲的就是實際的數(shù)據(jù),這種索引就是聚集索引。這個索引的key就是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引。
- InnoDB的輔助索引數(shù)據(jù)域存儲的也是相應記錄主鍵的值而不是地址,所以當以輔助索引查找時,會先根據(jù)輔助索引找到主鍵,再根據(jù)主鍵索引找到實際的數(shù)據(jù)。所以innodb不建議使用過長的主鍵,否則會使輔助索引變得過大。建議使用自增的字段作為主鍵,這樣B+Tree的每一個結(jié)點都會被順序的填滿,而不會頻繁的分裂調(diào)整,會有效的提升插入數(shù)據(jù)的效率。
2.3、Mylsam
MyIASM是MySQL默認的引擎,但是它沒有提供對數(shù)據(jù)庫事務的支持,也不支持行級鎖和外鍵,因此當INSERT或UPDATE數(shù)據(jù)時即寫操作需要鎖定整個表,效率便會低一些。MyIsam 存儲引擎獨立于操作系統(tǒng),也就是可以在windows上使用,也可以比較簡單的將數(shù)據(jù)轉(zhuǎn)移到linux操作系統(tǒng)上去。
適用場景:
- 不支持事務的設計,但是并不代表著有事務操作的項目不能用MyIsam存儲引擎,可以在service層進行根據(jù)自己的業(yè)務需求進行相應的控制。
- 不支持外鍵的表設計。
- 查詢速度很快,如果數(shù)據(jù)庫insert和update的操作比較多的話比較適用。
- 整天對表進行加鎖的場景。
- MyISAM極度強調(diào)快速讀取操作。
- MyIASM中存儲了表的行數(shù),于是SELECT COUNT(*) FROM TABLE時只需要直接讀取已經(jīng)保存好的值而不需要進行全表掃描。如果表的讀操作遠遠多于寫操作且不需要數(shù)據(jù)庫事務的支持,那么MyIASM也是很好的選擇。
缺點:就是不能在表損壞后主動恢復數(shù)據(jù)。
索引結(jié)構:
MyISAM索引結(jié)構:MyISAM索引用的B+ tree來儲存數(shù)據(jù),MyISAM索引的指針指向的是鍵值的地址,地址存儲的是數(shù)據(jù)。B+Tree的數(shù)據(jù)域存儲的內(nèi)容為實際數(shù)據(jù)的地址,也就是說它的索引和實際的數(shù)據(jù)是分開的,只不過是用索引指向了實際的數(shù)據(jù),這種索引就是所謂的非聚集索引。
2.4、InnoDB和Mylsam的區(qū)別:
-
事務:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持,提供事務支持已經(jīng)外部鍵等高級數(shù)據(jù)庫功能。
-
性能:MyISAM類型的表強調(diào)的是性能,其執(zhí)行數(shù)度比InnoDB類型更快。
-
行數(shù)保存:InnoDB 中不保存表的具體行數(shù),也就是說,執(zhí)行select count() fromtable時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數(shù)即可。注意的是,當count()語句包含where條件時,兩種表的操作是一樣的。
-
索引存儲:對于AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯(lián)合索引。MyISAM支持全文索引(FULLTEXT)、壓縮索引,InnoDB不支持。
MyISAM的索引和數(shù)據(jù)是分開的,并且索引是有壓縮的,內(nèi)存使用率就對應提高了不少。能加載更多索引,而Innodb是索引和數(shù)據(jù)是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
InnoDB存儲引擎被完全與MySQL服務器整合,InnoDB存儲引擎為在主內(nèi)存中緩存數(shù)據(jù)和索引而維持它自己的緩沖池。InnoDB存儲它的表&索引在一個表空間中,表空間可以包含數(shù)個文件(或原始磁盤分區(qū))。這與MyISAM表不同,比如在MyISAM表中每個表被存在分離的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制為2GB的操作系統(tǒng)上。 -
服務器數(shù)據(jù)備份:InnoDB必須導出SQL來備份,LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數(shù)據(jù)后再改成InnoDB表,但是對于使用的額外的InnoDB特性(例如外鍵)的表不適用。
MyISAM應對錯誤編碼導致的數(shù)據(jù)恢復速度快。MyISAM的數(shù)據(jù)是以文件的形式存儲,所以在跨平臺的數(shù)據(jù)轉(zhuǎn)移中會很方便。在備份和恢復時可單獨針對某個表進行操作。
InnoDB是拷貝數(shù)據(jù)文件、備份 binlog,或者用 mysqldump,在數(shù)據(jù)量達到幾十G的時候就相對痛苦了。 -
鎖的支持:MyISAM只支持表鎖。InnoDB支持表鎖、行鎖。行鎖大幅度提高了多用戶并發(fā)操作的能力。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。
3、MySQL的MVCC機制
MVCC是一種多版本并發(fā)控制機制,是MySQL的InnoDB存儲引擎實現(xiàn)隔離級別的一種具體方式,用于實現(xiàn)提交讀和可重復讀這兩種隔離級別。MVCC是通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)該機制,其在每行記錄后面保存兩個隱藏的列,分別保存這個行的創(chuàng)建版本號和刪除版本號,然后Innodb的MVCC使用到的快照存儲在Undo日志中,該日志通過回滾指針把一個數(shù)據(jù)行所有快照連接起來。
4、事務
事務(Transaction)是由一系列對系統(tǒng)中數(shù)據(jù)進行訪問與更新的操作所組成的一個程序執(zhí)行邏輯單元。事務是DBMS中最基礎的單位,事務不可分割。
事務具有4個基本特征,分別是:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Duration),簡稱ACID。
- 原子性(Atomicity)
原子性是指事務包含的所有操作要么全部成功,要么全部失敗回滾,因此事務的操作如果成功就必須要完全應用到數(shù)據(jù)庫,如果操作失敗則不能對數(shù)據(jù)庫有任何影響。
- 一致性(Consistency)
一致性是指事務必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。
拿轉(zhuǎn)賬來說,假設用戶A和用戶B兩者的錢加起來一共是5000,那么不管A和B之間如何轉(zhuǎn)賬,轉(zhuǎn)幾次賬,事務結(jié)束后兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。
- 隔離性(Isolation)
隔離性是當多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務,不能被其他事務的操作所干擾,多個并發(fā)事務之間要相互隔離。
即要達到這么一種效果:對于任意兩個并發(fā)的事務T1和T2,在事務T1看來,T2要么在T1開始之前就已經(jīng)結(jié)束,要么在T1結(jié)束之后才開始,這樣每個事務都感覺不到有其他事務在并發(fā)地執(zhí)行。
多個事務并發(fā)訪問時,事務之間是隔離的,一個事務不應該影響其它事務運行效果。這指的是在并發(fā)環(huán)境中,當不同的事務同時操縱相同的數(shù)據(jù)時,每個事務都有各自的完整數(shù)據(jù)空間。由并發(fā)事務所做的修改必須與任何其他并發(fā)事務所做的修改隔離。
不同的隔離級別:
- Read Uncommitted(讀取未提交[添加中文釋義]內(nèi)容):最低的隔離級別,什么都不需要做,一個事務可以讀到另一個事務未提交的結(jié)果。所有的并發(fā)事務問題都會發(fā)生。
- Read Committed(讀取提交內(nèi)容):只有在事務提交后,其更新結(jié)果才會被其他事務看見??梢越鉀Q臟讀問題。
- Repeated Read(可重復讀):在一個事務中,對于同一份數(shù)據(jù)的讀取結(jié)果總是相同的,無論是否有其他事務對這份數(shù)據(jù)進行操作,以及這個事務是否提交??梢越鉀Q臟讀、不可重復讀。
- Serialization(可串行化):事務串行化執(zhí)行,隔離級別最高,犧牲了系統(tǒng)的并發(fā)性??梢越鉀Q并發(fā)事務的所有問題。
- 持久性(Durability)
持久性是指一個事務一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務的操作。
例如我們在使用JDBC操作數(shù)據(jù)庫時,在提交事務方法后,提示用戶事務操作完成,當我們程序執(zhí)行完成直到看到提示后,就可以認定事務以及正確提交,即使這時候數(shù)據(jù)庫出現(xiàn)了問題,也必須要將我們的事務完全執(zhí)行完成,否則就會造成我們看到提示事務處理完畢,但是數(shù)據(jù)庫因為故障而沒有執(zhí)行事務的重大錯誤。
5、數(shù)據(jù)庫的三大范式
- 第一范式:當關系模式R的所有屬性都不能再分解為更基本的數(shù)據(jù)單位時,稱R是滿足第一范式,即屬性不可分。
- 第二范式:如果關系模式R滿足第一范式,并且R得所有非主屬性都完全依賴于R的每一個候選關鍵屬性,稱R滿足第二范式。
- 第三范式:設R是一個滿足第一范式條件的關系模式,X是R的任意屬性集,如果X非傳遞依賴于R的任意一個候選關鍵字,稱R滿足第三范式,即非主屬性不傳遞依賴于鍵碼。
6、數(shù)據(jù)庫的四種隔離級別
數(shù)據(jù)庫事務的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟讀、不可重復讀、幻讀這幾類問題。
- ISOLATION_READ_UNCOMMITTED:這是事務最低的隔離級別,它充許令外一個事務可以看到這 個事務未提交的數(shù)據(jù)。這種隔離級別會產(chǎn)生臟讀,不可重復讀和幻像讀。
- ISOLATION_READ_COMMITTED:保證一個事務修改的數(shù)據(jù)提交后才能被另外一個事務讀取。另外 一個事務不能讀取該事務未提交的數(shù)據(jù)
- ISOLATION_REPEATABLE_READ:這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現(xiàn)幻 像讀。它除了保證一個事務不能讀取另一個事務未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重 復讀)。
- ISOLATION_SERIALIZABLE:這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執(zhí) 行。除了防止臟讀,不可重復讀外,還避免了幻像讀。
第1級別:Read Uncommitted(讀取未提交內(nèi)容)
(1)所有事務都可以看到其他未提交事務的執(zhí)行結(jié)果。
(2)本隔離級別很少用于實際應用,因為它的性能也不比其他級別好多少。
(3)該級別引發(fā)的問題是——臟讀(Dirty Read):讀取到了未提交的數(shù)據(jù)。
第2級別:Read Committed(讀取提交內(nèi)容)
(1)這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別(但不是MySQL默認的)。
(2)它滿足了隔離的簡單定義:一個事務只能看見已經(jīng)提交事務所做的改變。
(3)這種隔離級別出現(xiàn)的問題是——不可重復讀(Nonrepeatable Read):不可重復讀意味著我們在同一個事務中執(zhí)行完全相同的select語句時可能看到不一樣的結(jié)果。
導致這種情況的原因可能有:
- 有一個交叉的事務有新的commit,導致了數(shù)據(jù)的改變;
- 一個數(shù)據(jù)庫被多個實例操作時,同一事務的其他實例在該實例處理其間可能會有新的commit。
第3級別:Repeatable Read(可重讀)
(1)這是MySQL的默認事務隔離級別。
(2)它確保同一事務的多個實例在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù)據(jù)行。
(3)此級別可能出現(xiàn)的問題——幻讀(Phantom Read):當用戶讀取某一范圍的數(shù)據(jù)行時,另一個事務又在該范圍內(nèi)插入了新行,當用戶再讀取該范圍的數(shù)據(jù)行時,會發(fā)現(xiàn)有新的“幻影” 行。
(4)InnoDB和Falcon存儲引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
第4級別:Serializable(可串行化)
(1)這是最高的隔離級別。
(2)它通過強制事務排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數(shù)據(jù)行上加上共享鎖。
(3)在這個級別,可能導致大量的超時現(xiàn)象和鎖競爭。
-
數(shù)據(jù)庫
+關注
關注
7文章
3839瀏覽量
64543 -
計算機網(wǎng)絡
+關注
關注
3文章
341瀏覽量
22200 -
MySQL
+關注
關注
1文章
819瀏覽量
26650
發(fā)布評論請先 登錄
相關推薦
評論