日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql面试考点_mysql面试知识点

發布時間:2024/7/19 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql面试考点_mysql面试知识点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 引擎-MyISAM和InnoDB的區別

a?是否支持行級鎖?:

MyISAM 只有表級鎖(table-level locking),

而InnoDB 支持行級鎖(row-level locking)和表級鎖,默認為行級鎖。

b?是否支持事務和崩潰后的安全恢復:

MyISAM?強調的是性能,每次查詢具有原子性,其執行速度比InnoDB類型更快,但是不提供事務支持。

但是InnoDB?提供事務支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

c 是否支持外鍵:

MyISAM不支持,而InnoDB支持。

d 是否支持MVCC?:

僅 InnoDB 支持。應對高并發事務, MVCC比單純的加鎖更高效;MVCC只在?READ COMMITTED?和?REPEATABLE READ?兩個隔離級別下工作;MVCC可以使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現;各數據庫中MVCC實現并不統一。

e 文件:

Innodb 創建表后生成的文件有:【聚簇索引】--【只在主鍵索引樹的葉子節點存儲了具體數據:節省磁盤】

frm:創建表的語句

idb:表里面的數據+索引文件

Myisam 創建表后生成的文件有:【非聚簇索引】---【查詢性能高】

frm:創建表的語句

MYD:表里面的數據文件(myisam data)

MYI:表里面的索引文件(myisam index)

f 樹節點值:

MyISAM:B+Tree葉節點的data域存放的是數據記錄的地址。在索引檢索的時候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其 data 域的值,然后以 data 域的值為地址讀取相應的數據記錄。這被稱為“非聚簇索引”。

InnoDB:其數據文件本身就是索引文件。相比MyISAM,索引文件和數據文件是分離的。InnoDB表數據文件本身就是按B+Tree組織的一個索引結構,樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這被稱為“聚簇索引(或聚集索引)”。而其余的索引都作為輔助索引,輔助索引的data域存儲相應記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據主索引搜索時,直接找到key所在的節點即可取出數據;在根據輔助索引查找時,則需要先取出主鍵的值,再走一遍主索引。?因此,在設計表的時候,不建議使用過長的字段作為主鍵,也不建議使用非單調的字段作為主鍵,這樣會造成主索引頻繁分裂。

2 索引

MySQL索引使用的數據結構主要有BTree索引?和?哈希索引?。

對于哈希索引來說,底層的數據結構就是哈希表,因此在絕大多數需求為單條記錄查詢的時候,可以選擇哈希索引,查詢性能最快;其余大部分場景,建議選擇BTree索引。

BTree索引使用的是B樹中的B+Tree,但對于主要的兩種存儲引擎的實現方式是不同的。

索引結構:【B+樹】

1.二叉查找樹也叫二叉排序樹,時間復雜度取決于樹高,為O(lgn)。但是樹可能不平衡,退化為鏈表,時間復雜度為O(n)

2.平衡二叉樹,做旋轉操作,所有節點的左右子樹高度不能超過1,時間復雜度O(lgn)。當插入數據時,需要1次旋轉維持平衡。刪除數據時,需要O(lgn)次維持平衡。

3.紅黑樹,根到葉子的最長的可能路徑不多于最短的可能路徑的兩倍長。插入或者刪除,O(1)次的旋轉或者變色。但是查詢慢。

4.B(B-)樹,每個非葉節點有多個子樹。矮胖子。局部性原理。緩存命中率高。每個節點存儲真實的數據。

5.B+樹,只有葉子節點存儲真實的數據,非葉子節點只存儲鍵。真實數據包括行的全部數據、主鍵、地址等。葉子節點之間通過雙向鏈表鏈接。

與B樹相比,優勢:

更少的IO次數。每個節點存儲的記錄數多,訪問時所需要的IO次數更少。這樣訪問局部性原理的利用更好,緩存命中率更高。

更適用范圍查詢。只對葉節點的指針鏈表進行遍歷即可。

更穩定的查詢效率:復雜度穩定為樹高,因為所有數據都在葉節點。

劣勢:

鍵重復時,占用空間大。

因此,最大優勢在于樹高更小。B+樹高度一般在2-4層。樹高由階數決定,階數越大樹越矮;而階數的大小又取決于每個節點可以存儲多少條記錄。

Innodb中每個節點使用一個頁(page),頁的大小為16KB,其中元數據只占大約128字節左右(包括文件管理頭信息、頁面頭信息等等),大多數空間都用來存儲數據。

對于非葉節點,記錄只包含索引的鍵和指向下一層節點的指針。假設每個非葉節點頁面存儲1000條記錄,則每條記錄大約占用16字節;當索引是整型或較短的字符串時,這個假設是合理的。延伸一下,我們經常聽到建議說索引列長度不應過大,原因就在這里:索引列太長,每個節點包含的記錄數太少,會導致樹太高,索引的效果會大打折扣,而且索引還會浪費更多的空間。

對于葉節點,記錄包含了索引的鍵和值(值可能是行的主鍵、一行完整數據等,具體見前文),數據量更大。這里假設每個葉節點頁面存儲100條記錄(實際上,當索引為聚簇索引時,這個數字可能不足100;當索引為輔助索引時,這個數字可能遠大于100;可以根據實際情況進行估算)。

對于一顆3層B+樹,第一層(根節點)有1個頁面,可以存儲1000條記錄;第二層有1000個頁面,可以存儲1000*1000條記錄;第三層(葉節點)有1000*1000個頁面,每個頁面可以存儲100條記錄,因此可以存儲1000*1000*100條記錄,即1億條。而對于二叉樹,存儲1億條記錄則需要26層左右。

那,為什么使用B+樹,不用hash呢?

1.hash需要把全部數據加載到內存中,如果數據量大,將非常消耗內存。采用B+樹,按照節點分段加載,會減少內存消耗。

2.唯一查找一個值時,hash更快。但是數據庫中經常查詢多條數據,由于B+樹數據的有序性,葉子節點有鏈表相連,查詢效率會快很多。

3 事務

事務是邏輯上的一組操作,要么都執行,要么都不執行。

事務最經典也經常被拿出來說例子就是轉賬了。假如小明要給小紅轉賬1000元,這個轉賬會涉及到兩個關鍵操作就是:將小明的余額減少1000元,將小紅的余額增加1000元。萬一在這兩個操作之間突然出現錯誤比如銀行系統崩潰,導致小明余額減少而小紅的余額沒有增加,這樣就不對了。事務就是保證這兩個關鍵操作要么都成功,要么都要失敗。

四大特性:

原子性(Atomicity):事務是最小的執行單位,不允許分割。事務的原子性確保動作要么全部完成,要么完全不起作用;

一致性(Consistency):?執行事務前后,數據保持一致,多個事務對同一個數據讀取的結果是相同的;

隔離性(Isolation):并發訪問數據庫時,一個用戶的事務不被其他事務所干擾,各并發事務之間數據庫是獨立的;

持久性(Durability):?一個事務被提交之后。它對數據庫中數據的改變是持久的,即使數據庫發生故障也不應該對其有任何影響。

4 并發事務的問題:

在典型的應用程序中,多個事務并發運行,經常會操作相同的數據來完成各自的任務(多個用戶對同一數據進行操作)。并發雖然是必須的,但可能會導致以下的問題。

臟讀(Dirty read):當一個事務正在訪問數據并且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時另外一個事務也訪問了這個數據,然后使用了這個數據。因為這個數據是還沒有提交的數據,那么另外一個事務讀到的這個數據是“臟數據”,依據“臟數據”所做的操作可能是不正確的。

丟失修改(Lost to modify):指在一個事務讀取一個數據時,另外一個事務也訪問了該數據,那么在第一個事務中修改了這個數據后,第二個事務也修改了這個數據。這樣第一個事務內的修改結果就被丟失,因此稱為丟失修改。 例如:事務1讀取某表中的數據A=20,事務2也讀取A=20,事務1修改A=A-1,事務2也修改A=A-1,最終結果A=19,事務1的修改被丟失。

不可重復讀(Unrepeatableread):指在一個事務內多次讀同一數據。在這個事務還沒有結束時,另一個事務也訪問該數據。那么,在第一個事務中的兩次讀數據之間,由于第二個事務的修改導致第一個事務兩次讀取的數據可能不太一樣。這就發生了在一個事務內兩次讀到的數據是不一樣的情況,因此稱為不可重復讀。

幻讀(Phantom read):幻讀與不可重復讀類似。它發生在一個事務(T1)讀取了幾行數據,接著另一個并發事務(T2)插入了一些數據時。在隨后的查詢中,第一個事務(T1)就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。

不可重復讀和幻讀區別:

不可重復讀的重點是修改比如多次讀取一條記錄發現其中某些列的值被修改,幻讀的重點在于新增或者刪除比如多次讀取一條記錄發現記錄增多或減少了。

5 事務隔離級別

READ-UNCOMMITTED(讀取未提交):最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致臟讀、幻讀或不可重復讀。

READ-COMMITTED(讀取已提交):?允許讀取并發事務已經提交的數據,可以阻止臟讀,但是幻讀或不可重復讀仍有可能發生。

REPEATABLE-READ(可重復讀):?對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發生。

SERIALIZABLE(可串行化):?最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。

默認隔離級別:

MySQL InnoDB 存儲引擎的默認支持的隔離級別是REPEATABLE-READ(可重讀)。使用的是Next-Key Lock 鎖算法,因此可以避免幻讀的產生。

InnoDB 存儲引擎在?分布式事務的情況下一般會用到?SERIALIZABLE(可串行化)?隔離級別。

6 鎖機制與InnoDB鎖算法

MyISAM和InnoDB存儲引擎使用的鎖:

MyISAM采用表級鎖(table-level locking)。

InnoDB支持行級鎖(row-level locking)和表級鎖,默認為行級鎖

表級鎖和行級鎖對比:

表級鎖:?MySQL中鎖定?粒度最大?的一種鎖,對當前操作的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。其鎖定粒度最大,觸發鎖沖突的概率最高,并發度最低,MyISAM和 InnoDB引擎都支持表級鎖。

行級鎖:?MySQL中鎖定?粒度最小?的一種鎖,只針對當前操作的行進行加鎖。 行級鎖能大大減少數據庫操作的沖突。其加鎖粒度最小,并發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

InnoDB存儲引擎的鎖的算法有三種:

Record lock:單個行記錄上的鎖

Gap lock:間隙鎖,鎖定一個范圍,不包括記錄本身。目的是為了阻止多個事務將記錄插入到同一范圍內,而這會導致幻讀問題的產生。有兩種方式顯式關閉gap鎖:(除了外鍵約束和唯一性檢查外,其余情況僅使用record lock) A. 將事務隔離級別設置為RC B. 將參數innodb_locks_unsafe_for_binlog設置為1

Next-key lock:record+gap 鎖定一個范圍,包含記錄本身。為了解決Phantom Problem幻讀問題。Innodb對于行的查詢使用next-key lock。當查詢的索引含有唯一屬性時,將next-key lock降級為record key。

7 表優化

當MySQL單表記錄數過大時,數據庫的CRUD性能會明顯下降,一些常見的優化措施如下:

a 限定數據的范圍

務必禁止不帶任何限制數據范圍條件的查詢語句。比如:我們當用戶在查詢訂單歷史的時候,我們可以控制在一個月的范圍內;

b 讀寫分離

經典的數據庫拆分方案,主庫負責寫,從庫負責讀;

c 垂直分區

根據數據庫里面數據表的相關性進行拆分。?例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。

簡單來說垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。

優點:?可以使得列數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易于維護。

缺點:?主鍵會出現冗余,需要管理冗余列,并會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加復雜;

d 水平分區

保持數據表結構不變,通過某種策略存儲數據分片。這樣每一片數據分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數據量。

水平拆分是指數據表行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的數據拆成多張表來存放。舉個例子:我們可以將用戶信息表拆分成多個用戶信息表,這樣就可以避免單一表數據量過大對性能造成影響。

水平拆分可以支持非常大的數據量。需要注意的一點是:分表僅僅是解決了單一表數據過大的問題,但由于表的數據還是在同一臺機器上,其實對于提升MySQL并發能力沒有什么意義,所以水平拆分最好分庫?。

水平拆分能夠?支持非常大的數據量存儲,應用端改造也少,但?分片事務難以解決?,跨節點Join性能較差,邏輯復雜。一般的數據表在優化得當的情況下支撐千萬以下的數據量是沒有太大問題的。如果實在要分片,盡量選擇客戶端分片架構,這樣可以減少一次和中間件的網絡I/O。

下面補充一下數據庫分片的兩種常見方案:

客戶端代理:?分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現。?當當網的?Sharding-JDBC?、阿里的TDDL是兩種比較常用的實現。

中間件代理:?在應用和數據中間加了一個代理層。分片邏輯統一維護在中間件服務中。?我們現在談的?Mycat?、360的Atlas、網易的DDB等等都是這種架構的實現。

8 池化思想

池化設計應該不是一個新名詞。我們常見的如java線程池、jdbc連接池、redis連接池等就是這類設計的代表實現。這種設計會初始預設資源,解決的問題就是抵消每次獲取資源的消耗,如創建線程的開銷,獲取遠程連接的開銷等。就好比你去食堂打飯,打飯的大媽會先把飯盛好幾份放那里,你來了就直接拿著飯盒加菜即可,不用再臨時又盛飯又打菜,效率就高了。除了初始化資源,池化設計還包括如下這些特征:池子的初始值、池子的活躍值、池子的最大值等,這些特征可以直接映射到java線程池和數據庫連接池的成員屬性中。

在連接池中,創建連接后,將其放置在池中,并再次使用它,因此不必建立新的連接。如果使用了所有連接,則會建立一個新連接并將其添加到池中。連接池還減少了用戶必須等待建立與數據庫的連接的時間。

數據庫連接本質就是一個 socket 的連接。數據庫服務端還要維護一些緩存和用戶權限信息之類的 所以占用了一些內存。我們可以把數據庫連接池是看做是維護的數據庫連接的緩存,以便將來需要對數據庫的請求時可以重用這些連接。為每個用戶打開和維護數據庫連接,尤其是對動態數據庫驅動的網站應用程序的請求,既昂貴又浪費資源。

9 如何做持久化

undo日志:

記錄的是修改前的值,在操作任何數據之前,首先將數據備份到一個地方(這個存儲數據備份的地方稱為Undo Log)。然后進行數據的修改。如果出現了錯誤或者用戶執行了ROLLBACK語句,系統可以利用Undo Log中的備份將數據恢復到事務開始之前的狀態。

舉例:

事務A要將字段age的值由原來的1修改為2,要將name的值由原來的Alice修改為Bob,

假設現在數據庫出現了宕機的問題,分為兩種情況:

如果在上表第三步之前數據庫掛了,則最終數據和日志均為原數據;

如果第三步及以后出現異常,則undo已經記錄了原來的值,則可以利用undo日志將數據恢復為原數據。

原理

當事務提交之后,undo不會被馬上刪除,而是放入待刪除隊列,由purge線程來判斷是否刪除和處理。在mysql5.6之前,undo只存在于共享表空間中,之后的版本中,則可以配置為獨立的文件。

undo內部默認128個回滾段槽(rseg slot),每個rseg slot內部有1024個回滾段(rollback segment)。其中:

slot0——共1個,預留給系統表空間

slot1~slot31——共31個,預留給臨時表空間

slot32~slot127——共96個,預留給undo獨立表空間

缺點:

由于undo日志會被清理掉,不能保證事務的持久性,因此才需要引入redo日志來保證事務的持久性。

redo日志:

記錄的是修改后最新的數據和冗余的undo日志,和Undo Log相反,Redo Log記錄的是新數據的備份。在事務提交前,只要將Redo Log持久化即可,不需要將數據持久化。當系統崩潰時,雖然數據沒有持久化,但是Redo Log已經持久化。系統可以根據Redo Log的內容,將所有數據恢復到最新的狀態。

舉例:

事務B要將字段age的值由原來的1修改為2,要將name的值由原來的Alice修改為Bob,redo日志記錄的過程表如下:

其中,redo日志必須先于數據寫入磁盤(即步驟8和步驟9的順序不能改變)。因為如果不這樣,在數據提交之后再寫redo日志,一旦redo日志的寫入過程出現異常,將無法保證持久性。

記錄redo日志時,先記入redo log buffer,最后再一起寫入磁盤,這樣可以減少IO,提升性能。

另外,未提交的事務和回滾了的事務也會計入redo日志。

mysql恢復的策略:

恢復時,先根據redo重做所有事務(包括未提交和回滾了的)。再根據undo回滾未提交的事務。

如上,如果事務B異常未提交事務就宕機,恢復時,先根據redo日志將數據恢復為age=2&name=Bob,然后再根據undo記錄的age=1&name=Alice將數據恢復如初。

如果事務C異常未提交事務就宕機,恢復時,根據redo日志,可以直接恢復至age=1&name=Alice的初始狀態。

redo日志會隨著時間推移而越來越大,為了提升redo的恢復性能,引入了checkpoint機制,在恢復的時候,只需要從checkpoint的位置往后恢復即可。

總結

以上是生活随笔為你收集整理的mysql面试考点_mysql面试知识点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。