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