今天我們用10分鐘,重點梳理一遍以下幾方面: 資料庫知識點彙總; 資料庫事務特性和隔離級別; 詳解關係型資料庫、索引與鎖機制; 資料庫調優與最佳實踐; 面試考察點及加分項。 一、資料庫的不同類型 1.常用的關係型資料庫 Oracle:功能強大,主要缺點就是貴 MySQL:互聯網行業中最流行的資料庫, ...
今天我們用10分鐘,重點梳理一遍以下幾方面:
- 資料庫知識點彙總;
- 資料庫事務特性和隔離級別;
- 詳解關係型資料庫、索引與鎖機制;
- 資料庫調優與最佳實踐;
- 面試考察點及加分項。
一、資料庫的不同類型
1.常用的關係型資料庫
- Oracle:功能強大,主要缺點就是貴
- MySQL:互聯網行業中最流行的資料庫,這不僅僅是因為MySQL的免費。可以說關係資料庫場景中你需要的功能,MySQL都能很好的滿足,後面詳解部分會詳細介紹MySQL的一些知識點
- MariaDB:是MySQL的分支,由開源社區維護,MariaDB雖然被看作MySQL的替代品,但它在擴展功能、存儲引擎上都有非常好的改進
- PostgreSQL:也叫PGSQL,PGSQL類似於Oracle的多進程框架,可以支持高併發的應用場景,PG幾乎支持所有的SQL標準,支持類型相當豐富。PG更加適合嚴格的企業應用場景,而MySQL更適合業務邏輯相對簡單、數據可靠性要求較低的互聯網場景。
2.NoSQL資料庫(非關係型資料庫)
- Redis:提供了持久化能力,支持多種數據類型。Redis適用於數據變化快且數據大小可預測的場景。
- MongoDB:一個基於分散式文件存儲的資料庫,將數據存儲為一個文檔,數據結構由鍵值對組成。MongoDB比較適合表結構不明確,且數據結構可能不斷變化的場景,不適合有事務和複雜查詢的場景。
- HBase:建立在HDFS,也就是Hadoop文件系統之上的分散式面向列的資料庫。類似於谷歌的大表設計,HBase可以提供快速隨機訪問海量結構化數據。在表中它由行排序,一個表有多個列族以及每一個列族可以有任意數量的列。 HBase依賴HDFS可以實現海量數據的可靠存儲,適用於數據量大,寫多讀少,不需要複雜查詢的場景。
- Cassandra:一個高可靠的大規模分散式存儲系統。支持分散式的結構化Key-value存儲,以高可用性為主要目標。適合寫多的場景,適合做一些簡單查詢,不適合用來做數據分析統計。
- Pika:一個可持久化的大容量類Redis存儲服務, 相容五種主要數據結構的大部分命令。Pika使用磁碟存儲,主要解決Redis大容量存儲的成本問題。
3.NewSQL資料庫(新一代關係型資料庫)
- TiDB:開源的分散式關係資料庫,幾乎完全相容MySQL,能夠支持水平彈性擴展、ACID事務、標準SQL、MySQL語法和MySQL協議,具有數據強一致的高可用特性。既適合線上事務處理,也適合線上分析處理。
- OceanBase:OceanBase是螞蟻金服的資料庫,OB是可以滿足金融級的可靠性和數據一致性要求的資料庫系統。當你需要使用事務,並且數據量比較大,就比較適合使用OB。不過目前OB已經商業化,不再開源。
二、事物特性及事物類型
後面的詳解知識點會展開介紹
三、資料庫的範式
前關係資料庫有六種範式:第一範式、第二範式、第三範式、巴斯-科德範式(BCNF)、第四範式和第五範式。範式級別越高對數據表的要求越嚴格。
- 第一範式要求最低,只要求表中欄位不可用在拆分。
- 第二範式在第一範式的基礎上要求每條記錄由主鍵唯一區分,記錄中所有屬性都依賴於主鍵。
- 第三範式在第二範式的基礎上,要求所有屬性必須直接依賴主鍵,不允許間接依賴。
- 一般說來,資料庫只需滿足第三範式就可以了。
詳解知識點一:資料庫事務
知識點
▌1.資料庫事務特性
資料庫的特性是面試時考察頻率非常高的題目,共4個特性:
- 原子性:是指事務由原子的操作序列組成,所有操作要麼全部成功,要麼全部失敗回滾。
- 一致性:是指事務的執行不能破壞資料庫數據的完整性和一致性,一個事務在執行之前和執行之後,資料庫都必須處以一致性狀態。比如在做多表操作時,多個表要麼都是事務後新的值,要麼都是事務前的舊值。
- 隔離性:是指多個用戶併發訪問資料庫時,資料庫為每個用戶執行的事務,不能被其他事務的操作所干擾,多個併發事務之間要相互隔離。事務的隔離級別我們稍後介紹。
- 持久性:是指一個事務一旦提交並執行成功,那麼對資料庫中數據的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。
▌2.事物併發問題與隔離級別
a.事務併發問題
- 臟讀:臟讀是指在一個事務處理過程里讀取了另一個未提交的事務中的數據,例如,賬戶A轉帳給B500元,B餘額增加後但事務還沒有提交完成,此時如果另外的請求中獲取的是B增加後的餘額,這就發生了臟讀,因為事務如果失敗回滾時,B的餘額就不應該增加。
- 不可重覆讀:不可重覆讀是指對於資料庫中某個數據,一個事務範圍內多次查詢返回了不同的數據值,這是由於在多次查詢之間,有其他事務修改了數據併進行了提交。
- 幻讀:是指一個事務中執行兩次完全相同的查詢時,第二次查詢所返回的結果集跟第一個查詢不相同。與不可重覆讀的區別在於,不可重覆讀是對同一條記錄,兩次讀取的值不同。而幻讀是記錄的增加或刪除,導致兩次相同條件獲取的結果記錄數不同。
b:事務的四種隔離級別
可以用於解決這幾種併發問題。如圖右面,由上到下的4種隔離級別由低到高。
- 級別1讀未提交:也就是可以讀取到其他事務未提交的內容,這是最低的隔離級別,這個隔離級別下,前面提到的三種併發問題都有可能發生。
- 級別2讀已提交:就是只能讀取到其他事務已經提交的數據。這個隔離級別可以解決臟讀問題。
- 級別三可重覆讀:可以保證整個事務過程中,對同數據的多次讀取結果是相同的。這個級別可以解決臟讀和不可重覆讀的問題。MySQL預設的隔離級別就是可重覆讀。
- 級別四串列化:這是最高的隔離級別,所有事務操作都依次順序執行。這個級別會導致併發度下降,性能最差。不過這個級別可以解決前面提到的所有併發問題。
▌3.事務分類
共分5大類:
- 扁平化事務:在扁平事務中,所有的操作都在同一層次,這也是我們平時使用最多的一種事務。它的主要限制是不能提交或者回滾事務的某一部分,要麼都成功,要麼都回滾。
- 帶保存點的扁平事務:為瞭解決第一種事務的弊端,就有了第二種帶保存點的扁平事務。它允許事務在執行過程中回滾到較早的狀態,而不是全部回滾。通過在事務中插入保存點,當操作失敗後,可以選擇回滾到最近的保存點處。
- 鏈事務:可以看做是第二種事務的變種。它在事務提交時,會將必要的上下文隱式傳遞給下一個事務,當事務失敗時就可以回滾到最近的事務。不過,鏈事務只能回滾到最近的保存點,而帶保存點的扁平化事務是可以回滾到任意的保存點。
- 嵌套事務:由頂層事務和子事務構成,類似於樹的結構。一般頂層事務負責邏輯管理,子事務負責具體的工作,子事務可以提交,但真正提交要等到父事務提交,如果上層事務回滾,那麼所有的子事務都會回滾。
- 分散式事務:是指分散式環境中的扁平化事務。
其中,常用的分散式事務解決方案共4種
a.XA協議:是保證強一致性的剛性事務。實現方式有兩段式提交和三段式提交。兩段式提交需要有一個事務協調者來保證所有的事務參與者都完成了第一階段的準備工作。如果協調者收到所有參與者都準備好的消息,就會通知所有的事務執行第二階段提交。一般場景下兩段式提交已經能夠很好得解決分散式事務了,然而兩階段在即使只有一個進程發生故障時,也會導致整個系統存在較長時間的阻塞。三段式提交通過增加Pre-commit階段來減少前面提到的系統阻塞的時間。三段式提交很少在實際中使用,簡單瞭解就可以了。
b.TCC:是滿足最終一致性的柔性事務方案。TCC採用補償機制,核心思想是對每個操作,都要註冊對應的確認和補償操作。它分為三個階段:Try階段主要對業務系統進行檢測及資源預留;Confirm階段對業務系統做確認提交。Cancel階段是在業務執行錯誤,執行回滾,釋放預留的資源。
c.消息事務:第三種方案是消息一致性方案。基本思路是將本地操作和發送消息放在一個事務中,保證本地操作和消息發送要麼都成功要麼都失敗。下游應用訂閱消息,收到消息後執行對應操作。
d.GTS/Fescar:阿裡雲中的全局事務服務GTS,對應的開源版本是Fescar。Fescar基於兩段式提交進行改良,剝離了分散式事務方案對資料庫在協議支持上的要求。使用Fescar的前提是分支事務中涉及的資源,必須是支持ACID事務的關係型資料庫。分支的提交和回滾機制,都依賴於本地事務來保障。 Fescar的實現目前還存在一些局限,比如事務隔離級別最高支持到讀已提交級別。
詳解知識點二:MySQL資料庫
▌1.常用SQL語句
需要能手寫常用SQL語句,這裡沒有什麼特殊的技巧,根據如圖列出的語句類型多做一些練習
▌2.數據類型
要知道MySQL都提供哪些基本都數據類型,不同數據類型占用的空間大小。
▌3.MySQL中主要的存儲引擎
MyISAM是MySQL官方提供的存儲引擎,其特點是支持全文索引,查詢效率比較高,缺點是不支持事務、使用表級鎖。InnoDB在5.5版本後成為了Mysql的預設存儲引擎,特點是支持ACID事務、支持外鍵、支持行級鎖提高了併發效率。TokuDB是第三方開發的開源存儲引擎,有非常快的寫速度,支持數據的壓縮存儲、可以線上添加索引而不影響讀寫操作。但是因為壓縮的原因,TokuDB非常適合訪問頻率不高的數據或歷史數據歸檔,不適合大量讀取的場景。
▌4.MySQL中的鎖
MyIASAM使用表級鎖,InnoDB使用行級鎖。表鎖開銷小,加鎖快,不會出現死鎖;但是鎖的粒度大,發生鎖衝突的概率高,併發訪問效率比較低。行級鎖開銷大,加鎖慢,有可能會出現死鎖,不過因為鎖定粒度最小,發生鎖衝突的概率低,併發訪問效率比較高。
註:
- 共用鎖也就是讀鎖,其他事務可以讀,但不能寫。MySQL可以通過Lock In Share Mode語句顯示使用共用鎖。
- 排他鎖就是寫鎖,其他事務不能讀取,也不能寫。對於Update、Delete和INSERT語句,InnoDB會自動給涉及的數據集加排他鎖,或者使用select for update顯示使用排他鎖。
▌5.索引
後文重點講解
▌6.MySQL的存儲過程與函數
存儲過程和函數都可以避免開發人員重覆編寫相同的SQL語句,並且存儲過程和函數都是在MySQL伺服器中執行的,可以減少客戶端和伺服器端的數據傳輸。
存儲過程能夠實現更複雜的功能,而函數一般用來實現針對性比較強的功能,例如特殊策略求和等。存儲過程可以執行包括修改表等一系列資料庫操作,而用戶定義函數不能用於執行修改全局資料庫狀態的操作。
存儲過程一般是作為一個獨立的部分來執行,而函數可以作為查詢語句的一個部分來調用。SQL語句中不能使用存儲過程,但可以使用函數。
不過存儲過程一般與資料庫實現綁定,使用存儲過程會降低程式的可移植性,應謹慎使用。
▌7.新特性
可以瞭解MySQL8.0的一些新特性,例如預設字元集格式改為了UTF8;增加了隱藏索引的功能,隱藏後的索引不會被查詢優化器使用,可以使用這個特性用於性能調試;支持了通用表表達式,使複雜查詢中的嵌入表語句更加清晰;新增了視窗函數的概念,它可以用來實現新的查詢方式。視窗函數與 SUM、COUNT等集合函數類似,但不會將多行查詢結果合併,而是將結果放在多行中。即視窗函數不需要GROUP BY。
▌8.MySQL調優
後文重點講解。
➔重點講解一:MySQL索引
索引可以大幅增加資料庫的查詢的性能,在實際業務場景中,或多或少都會使用到。
但是索引是有如下2個代價的:
a.需要額外的磁碟空間來保存索引
b.對於插入、更新、刪除等操作由於更新索引會增加額外的開銷
因此索引比較適合用在讀多寫少的場景。
▌1.MySQL索引類型
如左面的模塊,共分為5類:
- 唯一索引:就是索引列中的值必須是唯一的,但是允許出現空值。這種索引一般用來保證數據的唯一性,比如保存賬戶信息的表,每個賬戶的id必須保證唯一,如果重覆插入相同的賬戶id時會MySQL返回異常。
- 主鍵索引:是一種特殊的唯一索引,但是它不允許出現空值。
- 普通索引:與唯一索引不同,它允許索引列中存在相同的值。例如學生的成績表,各個學科的分數是允許重覆的,就可以使用普通索引。
- 聯合索引:就是由多個列共同組成的索引。一個表中含有多個單列的索引並不是聯合索引,聯合索引是對多個列欄位按順序共同組成一個索引。應用聯合索引時需要註意最左原則,就是Where查詢條件中的欄位必須與索引欄位從左到右進行匹配。比如,一個用戶信息表,用姓名和年齡組成了聯合索引,如果查詢條件是姓名等於張三,那麼滿足最左原則;如果查詢條件是年齡大於20,由於索引中最左的欄位是姓名不是年齡,所以不能使用這個索引。
- 全文索引:前面提到了,MyISAM引擎中實現了這個索引,在5.6版本後InnoDB引擎也支持了全文索引,並且在5.7.6版本後支持了中文索引。全文索引只能在CHAR,VARCHAR,TEXT類型欄位上使用,底層使用倒排索引實現。要註意對於大數據量的表,生成全文索引會非常消耗時間也非常消耗磁碟空間。
▌2.索引實現
如右面的模塊,索引實現共分4種形式:
- B+樹實現:b+樹比較適合用作'>'或'<'這樣的範圍查詢,是MySQL中最常使用的一種索引實現。
- R-tree:是一種用於處理多維數據的數據結構,可以對地理數據進行空間索引。不過實際業務場景中使用的比較少。
- Hash:是使用散列表來對數據進行索引,Hash方式不像Btree那樣需要多次查詢才能定位到記錄,因此Hash索引的效率高於B-tree,但是不支持範圍查找和排序等功能.實際使用的也比較少。
- FullText:就是我們前面提到的全文索引,是一種記錄關鍵字與對應文檔關係的倒排索引。
➔重點講解二:MySQL調優
MySQL的調優也是研發人員需要掌握的一項技能
一般MySQL調優有圖中的4個緯度:
- 針對資料庫設計、表結構設計以及索引設置緯度進行的優化;
- 對業務中使用的SQL語句進行優化,例如調整Where查詢條件;
- 對mysql服務的配置進行優化,例如對鏈接數的管理,對索引緩存、查詢緩存、排序緩存等各種緩存大小進行優化;
- 對硬體設備和操作系統設置進行優化,例如調整操作系統參數、禁用Swap、增加記憶體、升級固態硬碟等等。
這四個緯度從優化的成本角度來講,從左到右優化成本逐漸升高;從優化效果角度來看,從右到左優化的效果更高。
對於研發人員來說,前兩個緯度與業務息息相關,因此需要重點掌握,後兩個緯度更適合DBA進行深入學習,簡單瞭解就好。
本文將重點關註前兩個緯度
▌1.表結構和索引的優化
如左面的模塊,應該掌握如下6個原則:
第1個原則:要在設計表結構時,考慮資料庫的水平與垂直擴展能力,提前規劃好未來1年的數據量、讀寫量的增長,規劃好分庫分表方案。比如設計用戶信息表,預計1年後用戶數據10億條,寫QPS約5000,讀QPS30000,可以設計按UID緯度進行散列,分為4個庫每個庫32張表,單表數據量控制在KW級別;
第2個原則:要為欄位選擇合適的數據類型,在保留擴展能力的前提下,優先選用較小的數據結構。例如保存年齡的欄位,要使用TINYINT而不要使用INT;
第3個原則:可以將欄位多的表分解成多個表,必要時增加中間表進行關聯。假如一張表有4、50個欄位顯然不是一個好的設計;
第4個原則:是設計關係資料庫時需要滿足第三範式,但為了滿足第三範式,我們可能會拆分出多張表。而在進行查詢時需要對多張表進行關聯查詢,有時為了提高查詢效率,會降低範式的要求,在表中保存一定的冗餘信息,也叫做反範式。但要註意反範式一定要適度;
第5個原則:要擅用索引,比如為經常作為查詢條件的欄位創建索引、創建聯合索引時要根據最左原則考慮索引的復用能力,不要重覆創建索引;要為保證數據不能重覆的欄位創建唯一索引等等。不過要註意索引對插入、更新等寫操作是有代價的,不要濫用索引。比如像性別這樣唯一很差的欄位就不適合建立索引;
第6個原則:列欄位儘量設置為Not Null,MySQL難以對使用Null的列進行查詢優化,允許Null會使索引、索引統計和值更加複雜。允許Null值的列需要更多的存儲空間,還需要MySQL內部進行特殊處理。
▌2.SQL語句進行優化的原則
如右面的模塊,共分5個原則:
第1個原則:要找的最需要優化的SQL語句。要麼是使用最頻繁的語句,要麼是優化後提高最明顯的語句,可以通過查詢MySQL的慢查詢日誌來發現需要進行優化的SQL語句;
第2個原則:要學會利用MySQL提供的分析工具。例如使用Explain來分析語句的執行計劃,看看是否使用了索引,使用了哪個索引,掃描了多少記錄,是否使用文件排序等等。或者利用Profile命令來分析某個語句執行過程中各個分步的耗時;
第3個原則:要註意使用查詢語句是要避免使用Select *,而是應該指定具體需要獲取的欄位。原因一是可以避免查詢出不需要使用的欄位,二是可以避免查詢列欄位的元信息;
第4個原則:是儘量使用Prepared Statements,一個是性能更好,另一個是可以防止SQL註入;
第5個原則:是儘量使用索引掃描來進行排序,也就是儘量在有索引的欄位上進行排序操作。
以上為資料庫操作須掌握的內容,可以進行差缺補漏,希望對研發人員有一定的幫助。
面試考察點
1.必須瞭解資料庫的基本原理、使用場景以及常用隊列、資料庫的特點。MySQL提供了多種引擎可以支持事務型與非事務型的關係對象庫服務等等。
2.要深刻理解資料庫事務的ACID特性,瞭解併發事務可能導致的併發問題和不同的資料庫隔離級別如何解決這些併發問題。
3.要掌握常用的MySQL語句,比如WHERE條件查詢語句、JOIN關聯語句、ORDER BY排序語句等等。還要熟悉常用的自帶函數,例如SUM、COUNT等等。
4.要瞭解MySQL資料庫不同引擎的特點及不同類型的索引實現。比如最長使用的InnoDB非常擅長事務處理,MyISAM比較適合非事務的簡單查詢場景。比如知道MySQL的唯一索引、聯合索引、全文索引等不同索引類型,以及最長使用等B+樹索引實現等等。
面試加分項
1.要瞭解新特性,例如MySQL8.0中提供了視窗函數來支持新的查詢方式;支持通用表表達式,使複雜查詢中的嵌入表語句更加清晰等等。
2.要知道資料庫表設計原則,如果有過線上業務資料庫的設計經驗就更好了,你能夠知道如何對容量進行評估,也知道適當分庫分表來保證未來服務的可擴展性,這會對面試起到積極的影響。
3.最好有過資料庫調優經驗,例如明明建立了索引的語句,但是查詢效率還是很慢,通過Explain分析發現表中有多個索引,MySQL的優化器選用了錯誤的索引,導致查詢效率偏低,然後通過在SQL語句中使用Use Index來指定索引解決。