MySQL面試常見問題


在MySQL數據庫中,常用的引擎主要就是2個:Innodb和MyIASM。

首先:

1.簡單介紹這兩種引擎,以及該如何去選擇。
2.這兩種引擎所使用的數據結構是什么。

1.

a.Innodb引擎,Innodb引擎提供了對數據庫ACID事務的支持。並且還提供了行級鎖和外鍵的約束。它的設計的目標就是處理大數據容量的數據庫系統。它本身實際上是基於Mysql后台的完整的系統。Mysql運行的時候,Innodb會在內存中建立緩沖池,用於緩沖數據和索引。但是,該引擎是不支持全文搜索的。同時,啟動也比較的慢,它是不會保存表的行數的。當進行Select count(*) from table指令的時候,需要進行掃描全表。所以當需要使用數據庫的事務時,該引擎就是首選。由於鎖的粒度小,寫操作是不會鎖定全表的。所以在並發度較高的場景下使用會提升效率的。

b.MyIASM引擎,它是MySql的默認引擎,但不提供事務的支持,也不支持行級鎖和外鍵。因此當執行Insert插入和Update更新語句時,即執行寫操作的時候需要鎖定這個表。所以會導致效率會降低。不過和Innodb不同的是,MyIASM引擎是保存了表的行數,於是當進行Select count(*) from table語句時,可以直接的讀取已經保存的值而不需要進行掃描全表。所以,如果表的讀操作遠遠多於寫操作時,並且不需要事務的支持的。可以將MyIASM作為數據庫引擎的首先。

補充2點:

c.大容量的數據集時趨向於選擇Innodb。因為它支持事務處理和故障的恢復。Innodb可以利用數據日志來進行數據的恢復。主鍵的查詢在Innodb也是比較快的。

d.大批量的插入語句時(這里是INSERT語句)在MyIASM引擎中執行的比較的快,但是UPDATE語句在Innodb下執行的會比較的快,尤其是在並發量大的時候。

2.兩種引擎所使用的索引的數據結構是什么?

答案:都是B+樹!

MyIASM引擎,B+樹的數據結構中存儲的內容實際上是實際數據的地址值。也就是說它的索引和實際數據是分開的,只不過使用索引指向了實際數據。這種索引的模式被稱為非聚集索引。

Innodb引擎的索引的數據結構也是B+樹,只不過數據結構中存儲的都是實際的數據,這種索引有被稱為聚集索引

 

數據庫事務

什么是事務

事務是應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,一個事務中的一系列的操作要么全部成功,要么一個都不做。

事務的結束有兩種,當事務中的所以步驟全部成功執行時,事務提交。如果其中一個步驟失敗,將發生回滾操作,撤消撤消之前到事務開始時的所以操作。

事務的 ACID

事務具有四個特征:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持續性( Durability )。這四個特性簡稱為 ACID 特性。

1 、原子性。事務是數據庫的邏輯工作單位,事務中包含的各操作要么都做,要么都不做

2 、一致性。事 務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。因此當數據庫只包含成功事務提交的結果時,就說數據庫處於一致性狀態。如果數據庫系統 運行中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數據庫所做的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是 不一致的狀態。

3 、隔離性。一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的數據對其它並發事務是隔離的,並發執行的各個事務之間不能互相干擾。

4 、持續性。也稱永久性,指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。

Mysql的四種隔離級別

SQL標准定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的並發處理,並擁有更低的系統開銷。

Read Uncommitted(讀取未提交內容)

在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。

Read Committed(讀取提交內容)

這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別 也支持所謂的不可重復讀(Nonrepeatable Read),因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。

Repeatable Read(可重讀)

這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在並發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一范圍的數據行時,另一個事務又在該范圍內插入了新行,當用戶再讀取該范圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本並發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

Serializable(可串行化)

這是最高的隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。

這四種隔離級別采取不同的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:

臟讀(Drity Read):某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由於某些原因,前一個RollBack了操作,則后一個事務所讀取的數據就會是不正確的。

不可重復讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的數據。

幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例如有一個事務查詢了幾列(Row)數據,而另一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

 

 

海量數據的存儲

詳細內容參考:https://blog.csdn.net/u012129558/article/details/51491438

針對問題:海量數據的存儲和訪問成為了系統設計的瓶頸問題

解決方案:

數據庫水平切分的實現原理解析---分庫,分表,主從,集群,負載均衡器

水平切分數據庫,可以降低單台機器的負載,同時最大限度的降低了了宕機造成的損失;通過負載均衡策略,有效的降低了單台機器的訪問負載,降低了宕機的可能性;

通過集群方案,解決了數據庫宕機帶來的單點數據庫不能訪問的問題;

通過讀寫分離策略更是最大限度了提高了應用中讀取(Read)數據的速度和並發量。

 

數據切分

分庫降低了單點機器的負載;分表,提高了數據操作的效率,尤其是Write操作的效率

 

物理上的切分:分庫,對數據通過一系列的切分規則將數據分布到不同的DB服務器上,通過路由規則路由訪問特定的數據庫,這樣一來每次訪問面對的就不是單台服務器了,而是N台服務器,這樣就可以降低單台機器的負載壓力。

數據庫內的切分:分表,對數據通過一系列的切分規則,將數據分布到一個數據庫的不同表中,比如將article分為article_001,article_002等子表,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣做的目的其實也是很簡單的。

 

 

分庫的方法:

要想做到數據的水平切分(針對切分到不同機器上),在每一個表中都要有相冗余字符 作為切分依據和標記字段,通常的應用中我們選用user_id作為區分字段

(1)  user_id為區分

11000的對應DB110012000的對應DB2,以此類推;

優點:可部分遷移

缺點:數據分布不均

(2)hash取模分:

user_id進行hash(或者如果user_id是數值型的話直接使用user_id 的值也可),然后用一個特定的數字,比如應用中需要將一個數據庫切分成4個數據庫的話,我們就用4這個數字對user_idhash值進行取模運算,也就是user_id%4,這樣的話每次運算就有四種可能:結果為1的時候對應DB1;結果為2的時候對應DB2;結果為3的時候對應DB3;結果為0的時候對應DB4,這樣一來就非常均勻的將數據分配到4DB中。

優點:數據分布均勻

缺點:數據遷移的時候麻煩,不能按照機器性能分攤數據

(3)在認證庫中保存數據庫配置

就是建立一個DB,這個DB單獨保存user_idDB的映射關系,每次訪問數據庫的時候都要先查詢一次這個數據庫,以得到具體的DB信息,然后才能進行我們需要的查詢操作。

優點:靈活性強,一對一關系

缺點:每次查詢之前都要多一次查詢,性能大打折扣

 

分布式數據庫方案提供功能

1)提供分庫規則和路由規則(RouteRule簡稱RR),將上面的說明中提到的三中切分規則直接內嵌入本系統,具體的嵌入方式在接下來的內容中進行詳細的說明和論述;

2)引入集群(Group)的概念,保證數據的高可用性;

3)引入負載均衡策略(LoadBalancePolicy簡稱LB);

4)引入集群節點可用性探測機制,對單點機器的可用性進行定時的偵測,以保證LB策略的正確實施,以確保系統的高度穩定性;

5)引入讀/寫分離,提高數據的查詢速度;(Master負責寫入,slave負責讀,每個groupMasterSlave1:10MySQL大部分都是讀操作)

 

海量數據插入優化

詳情見:https://blog.csdn.net/iceblog/article/details/50686340

問題1:使用普通的單條插入效率非常低;

解決方法:使用PreparedStatement的addBatch()方法來批量插入

(Stringurl="jdbc:mysql://127.0.0.1/double?useServerPrepStmts=false&rewriteBatchedStatements=true";)這樣設置可以優化效率

 

問題2:4G內存的電腦,一次插入23W左右的數據時,內存溢出報錯;

解決方法:分批進行操作,每10W左右進行一次提交

 

問題3:對數據進行查詢時速度慢

解決方法:對mysql的表進行優化,插入索引,可以使用EXPLAIN [table]來看索引是否用上了

 

 

全文索引(倒排文檔技術)

正排索引是從文檔到關鍵字的映射(已知文檔求關鍵字),倒排索引是從關鍵字到文檔的映射(已知關鍵字求文檔)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM