MySQL常見面試題(持續更新)

MySQL常見面試題

事務四大特性

原子性:不可分割的操作單元,事務中所有操作,要麼全部成功;要麼撤回到執行事務之前的狀態
一致性:如果在執行事務之前數據庫是一致的,那麼在執行事務之後數據庫也還是一致的;
隔離性:事務操作之間彼此獨立和透明互不影響。事務獨立運行。這通常使用鎖來實現。一個事務處理後的結果,影響了其他事務,那麼其他事務會撤回。事務的100%隔離,需要犧牲速度。
持久性:事務一旦提交,其結果就是永久的。即便發生系統故障,也能恢復。

事務隔離級別

未提交讀(Read Uncommitted):允許髒讀,其他事務只要修改了數據,即使未提交,本事務也能看到修改後的數據值。也就是可能讀取到其他會話中未提交事務修改的數據
提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)。
可重複讀(Repeated Read):可重複讀。無論其他事務是否修改並提交了數據,在這個事務中看到的數據值始終不受其他事務影響。
串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

MySQL數據庫(InnoDB引擎)默認使用可重複讀( Repeatable read)

索引相關

數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用 B_TREE。B_TREE 索引加速了數據訪問,因爲存儲引擎不會再去掃描整張表得到需要的數據;相反,它從根節點開始,根節點保存了子節點的指針,存儲引擎會根據指針快速尋找數據。

MyISAM引擎使用B+Tree作爲索引結構,葉節點的data域存放的是數據記錄的地址,即:MyISAM索引文件和數據文件是分離的,MyISAM的索引文件僅僅保存數據記錄的地址。MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然後以data域的值爲地址,讀取相應數據記錄。MyISAM的索引方式也叫做“非聚集”的。

InnoDB引擎也使用B+Tree作爲索引結構,但是InnoDB的數據文件本身就是索引文件,葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這種索引叫做“聚焦索引”。InnoDB的輔助索引的data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作爲data域。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。InnoDB的索引實現後,不建議使用過長的字段作爲主鍵,因爲所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。在Innodb中也不建議使用非單調的字段作爲主鍵,因爲InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件爲了維持B+Tree的特性而頻繁的分裂調整,十分低效,建議使用自增字段作爲主鍵。

MySQL數據庫的四類索引:

index ---- 普通索引,數據可以重複,沒有任何限制。
  unique ---- 唯一索引,要求索引列的值必須唯一,但允許有空值;如果是組合索引,那麼列值的組合必須唯一。

primary key ---- 主鍵索引,是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值,一般是在創建表的同時創建主鍵索引。

組合索引 ---- 在多個字段上創建的索引,只有在查詢條件中使用了創建索引時的第一個字段,索引纔會被使用。

fulltext ---- 全文索引,是對於大表的文本域:char,varchar,text列才能創建全文索引,主要用於查找文本中的關鍵字,並不是直接與索引中的值進行比較。fulltext更像是一個搜索引擎,配合match against操作使用,而不是一般的where語句加like。

注:全文索引目前只有MyISAM存儲引擎支持全文索引,InnoDB引擎5.6以下版本還不支持全文索引

所有存儲引擎對每個表至少支持16個索引,總索引長度至少爲256字節,索引有兩種存儲類型,包括B型樹索引和哈希索引。

索引可以提高查詢的速度,但是創建和維護索引需要耗費時間,同時也會影響插入的速度,如果需要插入大量的數據時,最好是先刪除索引,插入數據後再建立索引。

索引生效條件

假設index(a,b,c)
最左前綴匹配:模糊查詢時,使用%匹配時:’a%‘會使用索引,’%a‘不會使用索引
條件中有or,索引不會生效
a and c,a生效,c不生效
b and c,都不生效
a and b > 5 and c,a和b生效,c不生效。

檢測索引的效果:

show status like ‘%handler_read%’ 越大越好

sql語句分類:

DDL:數據定義語言(create drop)
DML:數據操作語句(insert update delete)
DQL:數據查詢語句(select )
DCL:數據控制語句,進行授權和權限回收(grant revoke)
TPL:數據事務語句(commit collback savapoint)

數據庫三範式:

第一範式:1NF是對屬性的原子性約束,要求字段具有原子性,不可再分解;(只要是關係型數據庫都滿足1NF)

第二範式:2NF是在滿足第一範式的前提下,非主鍵字段不能出現部分依賴主鍵;解決:消除複合主鍵就可避免出現部分以來,可增加單列關鍵字。

第三範式:3NF是在滿足第二範式的前提下,非主鍵字段不能出現傳遞依賴,比如某個字段a依賴於主鍵,而一些字段依賴字段a,這就是傳遞依賴。解決:將一個實體信息的數據放在一個表內實現。

髒讀、幻讀、不可重複讀

髒讀: 是指事務T1將某一值修改,然後事務T2讀取該值,此後T1因爲某種原因撤銷對該值的修改,這就導致了T2所讀取到的數據是無效的。

不可重複讀 :是指在數據庫訪問時,一個事務範圍內的兩次相同查詢卻返回了不同數據。在一個事務內多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那麼在第一個事務中的兩次讀數據之間,由於第二個事務的修改,第一個事務兩次讀到的的數據可能是不一樣的。這樣在一個事務內兩次讀到的數據是不一樣的,因此稱爲是不可重複讀。

幻讀: 是指當事務不是獨立執行時發生的一種現象,比如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼就會發生,操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。

不可重複讀&幻讀區別:
如果使用鎖機制來實現這兩種隔離級別,在可重複讀中,該sql第一次讀取到數據後,就將這些數據加鎖,其它事務無法修改這些數據,就可以實現可重複讀了。但這種方法卻無法鎖住insert的數據,所以當事務A先前讀取了數據,或者修改了全部數據,事務B還是可以insert數據提交,這時事務A就會發現莫名其妙多了一條之前沒有的數據,這就是幻讀,不能通過行鎖來避免。需要Serializable隔離級別 ,讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,這麼做可以有效的避免幻讀、不可重複讀、髒讀等問題,但會極大的降低數據庫的併發能力。
不可重複讀重點在於update和delete,而幻讀的重點在於insert。如何通過鎖機制來解決他們產生的問題

存儲引擎 MyISAM 和 InnoDB區別:

InnoDB支持事務,MyISAM不支持。
MyISAM適合查詢以及插入爲主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用。
InnoDB支持外鍵,MyISAM不支持。
從MySQL5.5.5以後,InnoDB是默認引擎。
MyISAM支持全文類型索引,而InnoDB不支持全文索引。
InnoDB中不保存表的總行數,select count() from table時,InnoDB需要掃描整個表計算有多少行,但MyISAM只需簡單讀出保存好的總行數即可。注:當count()語句包含where條件時MyISAM也需掃描整個表。
對於自增長的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中可以和其他字段一起建立聯合索引。
清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MyISAM則會重建表。MyisAM使用delete語句刪除後並不會立刻清理磁盤空間,需要定時清理,命令:OPTIMIZE table dept;
InnoDB支持行鎖(某些情況下還是鎖整表,如 update table set a=1 where user like ‘%lee%’)
Myisam創建表生成三個文件:.frm 數據表結構 、 .myd 數據文件 、 .myi 索引文件,Innodb只生成一個 .frm文件,數據存放在ibdata1.log
現在一般都選用InnoDB,主要是MyISAM的全表鎖,讀寫串行問題,併發效率鎖表,效率低,MyISAM對於讀寫密集型應用一般是不會去選用的。
應用場景:

MyISAM不支持事務處理等高級功能,但它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
InnoDB用於需要事務處理的應用程序,包括ACID事務支持。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶併發操作的性能。

CHAR和VARCHAR的區別:

CHAR和VARCHAR類型在存儲和檢索方面有所不同
CHAR列長度固定爲創建表時聲明的長度,長度值範圍是1到255
當CHAR值被存儲時,它們被用空格填充到特定長度,檢索CHAR值時需刪除尾隨空格。

Mysql中的鎖類型

MyISAM支持表鎖,InnoDB支持表鎖和行鎖,默認爲行鎖
表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發量最低
行級鎖:開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的概率小,併發度最高

存儲過程

我們常用的操作數據庫語言SQL語句在執行的時候需要要先編譯,然後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲過程帶有參數)來調用執行它。

一個存儲過程是一個可編程的函數,它在數據庫中創建並保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫中的存儲過程可以看做是對編程中面向對象方法的模擬。它允許控制數據的訪問方式。

優點:

(1).存儲過程增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的運算。

(2).存儲過程允許標準組件是編程。存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。

(3).存儲過程能實現較快的執行速度。如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那麼存儲過程要比批處理的執行速度快很多。因爲存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

(4).存儲過程能過減少網絡流量。針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量並降低了網絡負載。

(5).存儲過程可被作爲一種安全機制來充分利用。系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。

delete、drop、truncate區別

truncate 和 delete只刪除數據,不刪除表結構 ,drop刪除表結構,並且釋放所佔的空間。
刪除數據的速度,drop> truncate > delete
delete屬於DML語言,需要事務管理,commit之後才能生效。drop和truncate屬於DDL語言,操作立刻生效,不可回滾。
使用場合:
當你不再需要該表時, 用 drop;
當你仍要保留該表,但要刪除所有記錄時, 用 truncate;
當你要刪除部分記錄時(always with a where clause), 用 delete.

注意: 對於有主外鍵關係的表,不能使用truncate而應該使用不帶where子句的delete語句,由於truncate不記錄在日誌中,不能夠激活觸發器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章