計算機考研複試面試常問問題 數據庫篇
在複習過程中,我用心查閱並整理了在考研複試面試中可能問到的大部分問題,並分點整理了答案,可以直接理解背誦並加上自己的語言潤色!極力推薦打印下來看,效率更高!絕對良心之作!
此係列一共有8篇:編程語言篇|數據結構篇|操作系統篇|組成原理篇|計算機網絡篇|數據庫篇|軟件工程篇|計算機專業英語篇(還未全部完成,敬請期待,你們的支持和關注是我最大的動力!)
個人整理,不可用於商業用途,轉載請註明出處。
作者各個平臺請搜索:程序員寶藏。快來探索屬於你的寶藏吧!
需要pdf直接打印版,可在公衆號"程序員寶藏"回覆複試上岸獲取(會持續更新)
需要408電子書最新版,可在公衆號"程序員寶藏"回覆408電子書獲取
需要408初試視頻最新版,可在公衆號"程序員寶藏"回覆408視頻獲取
需要複試機試視頻,可在公衆號"程序員寶藏"回覆機試必過獲取
相對於408初試,複試需要的少多了,加油,大家都可以上岸!!!讓我們一起努力!!!
章節導讀:
1.事務
概念:事務指的是滿足 ACID 特性的一組操作,可以通過 Commit 提交一個事務,也可以使用 Rollback 進行回滾。
ACID特性:
(1)原子性 (Atomicity):事務被視爲不可分割的最小單元,事務的所有操作要麼全部提交成功,要麼全部失敗回滾。回滾可以用回滾日誌來實現,回滾日誌記錄着事務所執行的修改操作,在回滾時反向執行這些修改操作即可。(2)一致性 (Consistency):數據庫在事務執行前後都保持一致性狀態。在一致性狀態下,所有事務對一個數據的讀取結果都是相同的。
(3)隔離性 (Isolation):一個事務所做的修改在最終提交以前,對其它事務是不可見的。
(4)持久性 (Durability):一旦事務提交,則其所做的修改將會永遠保存到數據庫中。即使系統發生崩潰,事務執行的結果也不能丟失。
使用重做日誌來保證持久性。
事務的 ACID 特性概念簡單,但不是很好理解,主要是因爲這幾個特性不是一種平級關係:
只有滿足一致性,事務的執行結果纔是正確的。
在無併發的情況下,事務串行執行,隔離性一定能夠滿足。此時只要能滿足原子性,就一定能滿足一致性。
在併發的情況下,多個事務並行執行,事務不僅要滿足原子性,還需要滿足隔離性,才能滿足一致性。事務滿足持久性是爲了能應對數據庫崩潰的情況。
2.併發一致性問題
丟失數據
丟失數據: 和 兩個事務都對一個數據進行修改, 先修改, 隨後修改, 的修改覆蓋了 的修改。簡記爲
同時修改
。
讀髒數據
讀髒數據: 對一個數據做了修改, 讀取這一個數據。若 執行 ROLLBACK 操作,則 讀取的結果和第一次的結果不一樣。簡記爲
讀取失敗的修改
。最簡單的場景是修改完成後,緊接着查詢檢驗結果。
不可重複讀
不可重複讀: 讀取一個數據, 對該數據做了修改。如果 再次讀取這個數據,此時讀取的結果和第一次讀取的結果不同。簡記爲
讀時修改
,重複讀取的結果不一樣。
幻影讀
幻影讀: 讀取某個範圍的數據, 在這個範圍內插入新的數據, 再次讀取這個範圍的數據,此時讀取的結果和和第一次讀取的結果不同。簡記爲
讀時插入
,重複讀取的結果不一樣。
解決方案
在併發環境下,事務的隔離性很難保證,因此會出現很多併發一致性問題。產生併發不一致性問題的主要原因是破壞了事務的隔離性。解決方法是通過
併發控制
來保證隔離性。併發控制可以通過封鎖
來實現,但是封鎖操作需要用戶自己控制,相當複雜。數據庫管理系統提供了事務的隔離級別
,讓用戶以一種更輕鬆的方式處理併發一致性問題。
3.封鎖
封鎖粒度
MySQL 中提供了兩種封鎖粒度:行級鎖
以及表級鎖
。應儘量只鎖定需要修改的那部分數據,而不是所有的資源。鎖定的數據量越少,發生鎖爭用的可能就越小,系統的併發程度就越高。但是加鎖需要消耗資源,鎖的各種操作 (包括獲取鎖、釋放鎖、以及檢查鎖狀態) 都會增加系統開銷。因此封鎖粒度越小,系統開銷就越大。爲此,我們在選擇封鎖粒度時,需在
鎖開銷
和併發程度
之間做一個權衡
。
封鎖類型
(1)讀寫鎖
排它鎖 (Exclusive),簡寫爲X 鎖
,又稱寫鎖
。共享鎖 (Shared),簡寫爲
S 鎖
,又稱讀鎖
。有以下兩個規定:
一個事務對數據對象 A 加了 X 鎖,就可以對 A 進行讀取和更新。加鎖期間其它事務不能對 A 加任何鎖。一個事務對數據對象 A 加了 S 鎖,可以對 A 進行讀取操作,但是不能進行更新操作。加鎖期間其它事務能對 A 加 S 鎖,但是不能加 X 鎖。
(2)意向鎖
使用意向鎖 (Intention Locks),可以更容易地支持多粒度封鎖,使得行鎖和表鎖能夠共存。
在存在行級鎖和表級鎖的情況下,事務 T 想要對錶 A 加 X 鎖,就需要先檢測是否有其它事務對錶 A 或者表 A 中的任意一行加了鎖,那麼就需要對錶 A 的每一行都檢測一次,這是非常耗時的。意向鎖在原來的 X/S 鎖之上引入了 IX / IS,IX / IS 都是
表級別的鎖
,用來表示一個事務稍後會對錶中的某個數據行上加 X 鎖或 S 鎖。整理可得以下兩個規定:一個事務在獲得某個數據行對象的 S 鎖之前,必須先獲得表的 IS 鎖或者更強的鎖;
一個事務在獲得某個數據行對象的 X 鎖之前,必須先獲得表的 IX 鎖。
封鎖協議
三級封鎖協議
一級封鎖協議
:事務 T 要修改數據 A 時必須加 X 鎖,直到 T 結束才釋放鎖。防止同時修改
,可解決丟失修改
問題,因不能同時有兩個事務對同一個數據進行修改,那麼事務的修改就不會被覆蓋。
二級封鎖協議
:在一級的基礎上,要求讀取數據 A 時必須加 S 鎖,讀取完馬上釋放 S 鎖。防止修改時讀取
,可解決丟失修改
和讀髒數據
問題,因爲一個事務在對數據 A 進行修改,根據 1 級封鎖協議,會加 X 鎖,那麼就不能再加 S 鎖了,也就是不會讀入數據。
三級封鎖協議
:在二級的基礎上,要求讀取數據 A 時必須加 S 鎖,直到事務結束了才能釋放 S 鎖。防止讀取時修改
,可解決丟失修改
和讀髒數據
問題,還進一步防止了不可重複讀
的問題,因爲讀 A 時,其它事務不能對 A 加 X 鎖,從而避免了在讀的期間數據發生改變。
兩段鎖協議
兩段鎖協議是指每個事務的執行可以分爲兩個階段:生長階段 (加鎖階段) 和衰退階段 (解鎖階段)。
兩段封鎖法可以這樣來實現:事務開始後就處於加鎖階段,一直到執行 ROLLBACK 和 COMMIT 之前都是加鎖階段。
ROLLBACK 和 COMMIT 使事務進入解鎖階段,即在 ROLLBACK 和 COMMIT 模塊中 DBMS 釋放所有封鎖。
4.關係數據庫設計理論
函數依賴
- 記 表示 A 函數決定 B,也可以說 B 函數依賴於 A。
- 若 是關係的一個或多個屬性的集合,該集合函數決定了關係的其它所>有屬性並且是
最小的
,那麼該集合就稱爲鍵碼
。- 對於 ,如果能找到 A 的真子集 ,使得 ,那麼 就是
部分函數>依賴
,否則就是完全函數依賴
。- 對於 ,,則 是一個
傳遞函數依賴
。
異常
- 如表所示,展示了學生課程關係的函數依賴爲 {Sno, Cname} -> {Sname, Sdept, Mname, Grade},鍵碼爲 {Sno, Cname}。也就是說,確定學生和課程後就能確定其它信息。
Sno | Sname | Sdept | Mname | Cname | Grade |
---|---|---|---|---|---|
1 | 學生-1 | 學院-1 | 院長-1 | 課程-1 | 90 |
2 | 學生-2 | 學院-2 | 院長-2 | 課程-2 | 80 |
2 | 學生-2 | 學院-2 | 院長-2 | 課程-1 | 100 |
3 | 學生-3 | 學院-2 | 院長-2 | 課程-2 | 95 |
不符合範式的關係,會產生很多異常,主要有以下四種異常:
冗餘數據
:例如學生-2
出現了兩次。
修改異常
:修改了一個記錄中的信息,但是另一個記錄中相同的信息卻沒有被修改。
刪除異常
:刪除一個信息,那麼也會丟失其它信息。例如刪除了課程-1
需要刪除第一>行和第三行,那麼 學生-1 的信息就會丟失。
插入異常
:例如想要插入一個學生的信息,如果這個學生還沒選課,那麼就無法插入。
範式
範式理論是爲了解決以上提到四種異常。高級別範式的依賴於低級別的範式,1NF 是最低級別的範式。
第一範式 (1NF)
屬性不可分。即數據庫表的每一列都是不可分割的基本數據項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。
第二範式 (2NF)
每個非主屬性完全函數依賴於鍵碼。可以通過分解來滿足 2NF。
分解前:
Sno | Sname | Sdept | Mname | Cname | Grade |
---|---|---|---|---|---|
1 | 學生-1 | 學院-1 | 院長-1 | 課程-1 | 90 |
2 | 學生-2 | 學院-2 | 院長-2 | 課程-2 | 80 |
2 | 學生-2 | 學院-2 | 院長-2 | 課程-1 | 100 |
3 | 學生-3 | 學院-2 | 院長-2 | 課程-2 | 95 |
以下學生課程關係中,{Sno, Cname} 爲鍵碼,有如下函數依賴:
- Sno -> Sname, Sdept
- Sdept -> Mname
- Sno, Cname-> Grade
函數依賴狀況分析:
Grade 完全函數依賴於鍵碼,它沒有任何冗餘數據,每個學生的每門課都有特定的成績。Sname, Sdept 和 Mname 都部分依賴於鍵碼,當一個學生選修了多門課時,這些數據就會出現多次,造成大量冗餘數據。
分解後:
關係-1:
Sno | Sname | Sdept | Mname |
---|---|---|---|
1 | 學生-1 | 學院-1 | 院長-1 |
2 | 學生-2 | 學院-2 | 院長-2 |
3 | 學生-3 | 學院-2 | 院長-2 |
- 有以下函數依賴:
- Sno -> Sname, Sdept
- Sdept -> Mname
- 關係-2:
Sno | Cname | Grade |
---|---|---|
1 | 課程-1 | 90 |
2 | 課程-2 | 80 |
2 | 課程-1 | 100 |
3 | 課程-2 | 95 |
- 有以下函數依賴: Sno, Cname Grade
第三範式 (3NF)
- 非主屬性不傳遞函數依賴於鍵碼。簡而言之,第三範式就是屬性不依賴於其它非主屬性。
- 上面的 關係-1 中存在以下傳遞函數依賴:Sno Sdept Mname。
分解後
- 關係-1.1:
Sno | Sname | Sdept |
---|---|---|
1 | 學生-1 | 學院-1 |
2 | 學生-2 | 學院-2 |
3 | 學生-3 | 學院-2 |
- 關係-1.2:
Sdept | Mname |
---|---|
學院-1 | 院長-1 |
學院-2 | 院長-2 |
巴斯-科德範式(BCNF)
Boyce-Codd Normal Form(巴斯-科德範式)
在3NF基礎上,任何非主屬性不能對主鍵子集依賴(在3NF基礎上消除對主碼子集的依賴)
巴斯-科德範式(BCNF)是第三範式(3NF)的一個子集,即滿足巴斯-科德範式(BCNF)必須滿>足第三範式(3NF)。通常情況下,巴斯-科德範式被認爲沒有新的設計規範加入,只是對第二範式與第三範式中設計規範要求更強,因而被認爲是修正第三範式,也就是說,它事實上是對第三範式的修正,使數據庫冗餘度更小。這也是BCNF不被稱爲第四範式的原因。某些書上,根據範式要求的遞增性將其稱之爲第四範式是不規範,也是更讓人不容易理解的地方。而真正的第四範式,則是在設計規範中添加了對多值及依賴的要求。
5.ER 圖
實體關係圖 (Entity-Relationship,E-R),有三個組成部分:實體、屬性、聯繫。用來進行關係型數據庫系統的概念設計。
實體
:用矩形表示,矩形框內寫明實體名.屬性
:用橢圓形表示,並用無向邊將其與相應的實體連接起來。聯繫
:用菱形表示,菱形框內寫明聯繫名,並用無向邊分別與有關實體連接起來,同時在無向>邊旁標上聯繫的類型(1…1,1…* 或 *…*)就是指存在的三種關係 (一對一、一對多或多對多)。
- ER 模型轉換爲關係模式的原則:
一對一
:遇到一對一關係的話,在兩個實體任選一個添加另一個實體的主鍵即可。一對多
:遇到一對多關係的話,在多端添加另一端的主鍵。多對多
:遇到多對多關係的話,我們需要將聯繫轉換爲實體,然後在該實體上加上另外兩個實體的主鍵,作爲聯繫實體的主鍵,然後再加上該聯繫自身帶的屬性即可。
6.索引
索引的數據結構
B-Tree (平衡樹, Balance Tree):也稱爲
多路平衡查找樹
,並且所有葉子節點位於同一層。
B+Tree:它不僅具有 B-Tree 的平衡性,並且可通過
順序訪問指針
來提高區間查詢
的性能。在 B+Tree 中,一個節點中的 key 從左到右非遞減排列,若某個指針的 左右相鄰分別是 和 ,且不爲 null,則該指針指向節點的所有 key 滿足 。
B+Tree 與 B-Tree 最大區別是,B+Tree 的非葉子結點不保存數據,只用於索引,所有數據都保存在葉子結點中。而且葉子結點間按照從小到大順序鏈接起來。
B-Tree/B+Tree 的增刪改查:
查找操作
:首先在根節點
進行二分查找
,找到一個 key 所在的指針,然後遞歸地在指針所指向的節點進行查找。直到查找到葉子節點,然後在葉子節點
上進行二分查找
,找出 key 所對應的 data。二分查找要求表有序,正好 B-Tree 和 B+Tree 結點中的 key 從左到右非遞減有序排列。
增刪操作
:會破壞平衡樹的平衡性,因此在插入刪除操作之後,需要對樹進行一個分裂、合併、旋轉等操作來維護平衡性。
MySQL 索引
索引,在 MySQL 也稱爲鍵 (Key),是
存儲引擎
快速找到記錄的一種數據結構
。相當於圖書的目錄,可根據目錄中的頁碼快速找到所需的內容。
索引結構類型
(1)B+Tree 索引
- B+Tree 索引是大多數 MySQL 存儲引擎的默認索引類型。
- 因爲 B+ Tree 的
有序性
,因此可用於部分查找
、範圍查找
、排序
和分組
。 - 適用於全鍵值、鍵值範圍和鍵前綴查找,其中鍵前綴查找只適用於最左前綴查找。若不是按照索引列的順序進行查找,則無法使用索引。
(2)Hash 索引
-
Hash 索引能以 O(1) 時間進行查找,但是失去了有序性。因此無法用於排序與分組,無法用於部分查找和範圍查找,只支持
精確查找
。Hash 索引僅滿足
=
,IN
和<=>
查詢,不能使用範圍查詢。因爲 Hash 索引比較的是 Hash 運算後的 Hash 值,所以它只能用於等值的過濾。
(3)全文索引
- 全文索引使用倒排索引實現,它記錄着關鍵詞到其所在文檔的映射。
(4)空間數據索引
- 空間數據索引會從所有維度來索引數據,可以有效地使用任意維度來進行組合查詢。
- 必須使用 GIS 相關的函數來維護數據。
索引的優點缺點
優點
-
大大減少了服務器需要掃描的數據行數。
-
避免服務器進行排序和分組操作,以避免創建
臨時表
。B+Tree 索引是有序的,可以用於 ORDER BY 和 GROUP BY 操作。臨時表主要是在排序和分組過程中創建,不需要排序和分組,也就不需要創建臨時表。
-
將
隨機 I/O
變爲順序 I/O
。B+Tree 索引是有序的,會將相鄰的數據都存儲在一起。
缺點
- 索引並不是越多越好,索引固然可以提高相應的 SELECT 的效率,但同時也降低了 INSERT 及 UPDATE 的效率,因爲 INSERT 或 UPDATE 時有可能會
重建索引
。
索引的設計原則
從索引的優、缺點考慮索引的設計原則。
忌過度索引
:索引需要額外的磁盤空間,而且會降低寫操作的性能。- 在修改表內容時,索引會進行更新甚至重構,索引列越多花銷時間越長。爲此優化檢索性能,只保持需要的索引即可。
- 經常用在
排列
、分組
和範圍搜索
的列適合創建索引,因爲索引是有序的。 - 經常出現在
WHERE
子句的列,或是JOIN
連接子句中指定的列適合創建索引。
使用短索引
:若對長字符串列進行索引,應該指定一個前綴長度,這樣能夠節省大量索引空間。
索引的優化策略
-
獨立的列
:在進行查詢時,索引列不能是表達式
的一部分,也不能是函數參數
,否則無法使用索引。 -
多列索引
:在需要使用多個列作爲條件進行查詢時,使用多列索引比使用多個單列索引性能更好。 -
索引列的順序
:讓選擇性最強的索引列放在前面。 -
前綴索引
:對於 BLOB、TEXT 和 VARCHAR 類型的列,必須使用前綴索引,只索引開始的部分字符。前綴長度的選取需要根據索引選擇性來確定。 -
覆蓋索引
:索引包含所有需要查詢的字段的值。具有以下優點:- 索引通常遠小於數據行的大小,只讀取索引能大大減少數據訪問量。
- 一些存儲引擎(例如 MyISAM)在內存中只緩存索引,而數據依賴於操作系統來緩存。因此,只訪問索引可以不使用系統調用(通常比較費時)。
索引的使用場景
- 對於
非常小的表
:大部分情況下簡單的全表掃描
比建立索引更高效; - 對於
中大型的表
:建立索引
非常有效; - 對於
特大型的表
:建立和維護索引的代價將會隨之增長。這種情況下,需要用到一種技術可以直接區分出需要查詢的一組數據,而不是一條記錄一條記錄地匹配。例如可以使用分區技術
。