MySQL數據庫的核心知識點

今天,數據庫的操作越來越成為整個應用的性能瓶頸了,這點對於 Web 應用尤

其明顯。關於數據庫的性能,這並不只是 DBA 才需要擔心的事,而這更是我們

程序員需要去關注的事情。當我們去設計數據庫表結構,對操作數據庫時(尤其

是查表時的 SQL 語句),我們都需要注意數據操作的性能。這裡,我們不會講過

多的 SQL 語句的優化,而只是針對 MySQL 這一 Web 應用最多的數據庫。希望下

面的這些優化技巧對你有用。

數據庫的使用,是開發人員的基本功,對它掌握越清晰越深入,你能做的事情就越多。

做業務,要懂基本的SQL語句;

做性能優化,要懂索引,懂引擎;

做分庫分表,要懂主從,懂讀寫分離...

今天我們用10分鐘,重點梳理一遍以下幾方面:

  • 數據庫知識點彙總;數據庫事務特性和隔離級別;詳解關係型數據庫、索引與鎖機制;數據庫調優與最佳實踐;面試考察點及加分項。

知識點彙總

MySQL數據庫的核心知識點

一、數據庫的不同類型

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.事物併發問題與隔離級別

MySQL數據庫的核心知識點

a.事務併發問題

  • 髒讀:髒讀是指在一個事務處理過程裡讀取了另一個未提交的事務中的數據,例如,賬戶A轉帳給B500元,B餘額增加後但事務還沒有提交完成,此時如果另外的請求中獲取的是B增加後的餘額,這就發生了髒讀,因為事務如果失敗回滾時,B的餘額就不應該增加。不可重複讀:不可重複讀是指對於數據庫中某個數據,一個事務範圍內多次查詢返回了不同的數據值,這是由於在多次查詢之間,有其他事務修改了數據並進行了提交。幻讀:是指一個事務中執行兩次完全相同的查詢時,第二次查詢所返回的結果集跟第一個查詢不相同。與不可重複讀的區別在於,不可重複讀是對同一條記錄,兩次讀取的值不同。而幻讀是記錄的增加或刪除,導致兩次相同條件獲取的結果記錄數不同。

b:事務的四種隔離級別

可以用於解決這幾種併發問題。如圖右面,由上到下的4種隔離級別由低到高。

  • 級別1讀未提交:也就是可以讀取到其他事務未提交的內容,這是最低的隔離級別,這個隔離級別下,前面提到的三種併發問題都有可能發生。級別2讀已提交:就是隻能讀取到其他事務已經提交的數據。這個隔離級別可以解決髒讀問題。級別三可重複讀:可以保證整個事務過程中,對同數據的多次讀取結果是相同的。這個級別可以解決髒讀和不可重複讀的問題。MySQL默認的隔離級別就是可重複讀。級別四串行化:這是最高的隔離級別,所有事務操作都依次順序執行。這個級別會導致併發度下降,性能最差。不過這個級別可以解決前面提到的所有併發問題。

▌3.事務分類

共分5大類:

  • 扁平化事務:在扁平事務中,所有的操作都在同一層次,這也是我們平時使用最多的一種事務。它的主要限制是不能提交或者回滾事務的某一部分,要麼都成功,要麼都回滾。帶保存點的扁平事務:為了解決第一種事務的弊端,就有了第二種帶保存點的扁平事務。它允許事務在執行過程中回滾到較早的狀態,而不是全部回滾。通過在事務中插入保存點,當操作失敗後,可以選擇回滾到最近的保存點處。鏈事務:可以看做是第二種事務的變種。它在事務提交時,會將必要的上下文隱式傳遞給下一個事務,當事務失敗時就可以回滾到最近的事務。不過,鏈事務只能回滾到最近的保存點,而帶保存點的扁平化事務是可以回滾到任意的保存點。嵌套事務:由頂層事務和子事務構成,類似於樹的結構。一般頂層事務負責邏輯管理,子事務負責具體的工作,子事務可以提交,但真正提交要等到父事務提交,如果上層事務回滾,那麼所有的子事務都會回滾。分佈式事務:是指分佈式環境中的扁平化事務。
MySQL數據庫的核心知識點

其中,常用的分佈式事務解決方案共4種

a.XA協議:是保證強一致性的剛性事務。實現方式有兩段式提交和三段式提交。兩段式提交需要有一個事務協調者來保證所有的事務參與者都完成了第一階段的準備工作。如果協調者收到所有參與者都準備好的消息,就會通知所有的事務執行第二階段提交。一般場景下兩段式提交已經能夠很好得解決分佈式事務了,然而兩階段在即使只有一個進程發生故障時,也會導致整個系統存在較長時間的阻塞。三段式提交通過增加Pre-commit階段來減少前面提到的系統阻塞的時間。三段式提交很少在實際中使用,簡單瞭解就可以了。

b.TCC:是滿足最終一致性的柔性事務方案。TCC採用補償機制,核心思想是對每個操作,都要註冊對應的確認和補償操作。它分為三個階段:Try階段主要對業務系統進行檢測及資源預留;Confirm階段對業務系統做確認提交。Cancel階段是在業務執行錯誤,執行回滾,釋放預留的資源。

c.消息事務:第三種方案是消息一致性方案。基本思路是將本地操作和發送消息放在一個事務中,保證本地操作和消息發送要麼都成功要麼都失敗。下游應用訂閱消息,收到消息後執行對應操作。

d.GTS/Fescar:阿里雲中的全局事務服務GTS,對應的開源版本是Fescar。Fescar基於兩段式提交進行改良,剝離了分佈式事務方案對數據庫在協議支持上的要求。使用Fescar的前提是分支事務中涉及的資源,必須是支持ACID事務的關係型數據庫。分支的提交和回滾機制,都依賴於本地事務來保障。 Fescar的實現目前還存在一些侷限,比如事務隔離級別最高支持到讀已提交級別。

詳解知識點二:MySQL數據庫

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索引

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的調優也是研發人員需要掌握的一項技能

一般MySQL調優有圖中的4個緯度:

  • 針對數據庫設計、表結構設計以及索引設置緯度進行的優化;對業務中使用的SQL語句進行優化,例如調整Where查詢條件;對mysql服務的配置進行優化,例如對鏈接數的管理,對索引緩存、查詢緩存、排序緩存等各種緩存大小進行優化;對硬件設備和操作系統設置進行優化,例如調整操作系統參數、禁用Swap、增加內存、升級固態硬盤等等。

這四個緯度從優化的成本角度來講,從左到右優化成本逐漸升高;從優化效果角度來看,從右到左優化的效果更高。

對於研發人員來說,前兩個緯度與業務息息相關,因此需要重點掌握,後兩個緯度更適合DBA進行深入學習,簡單瞭解就好。

本文將重點關注前兩個緯度

MySQL數據庫的核心知識點

▌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來指定索引解決。

受限文章的篇幅問題,我這邊還準備了MySQL數據庫性能優化的最佳實踐PDF,

各位有需要的可以關注我後私信回覆【架構資料】即可免費獲取!

MySQL數據庫的核心知識點

相關推薦

推薦中...