Mysql理論面試

1.數據庫三大範式通俗解釋

一範式就是屬性不可分割。屬性是什麼?就是表中的字段。
不可分割的意思就按字面理解就是最小單位,不能再分成更小單位了。
這個字段只能是一個值,不能被拆分成多個字段,否則的話,它就是可分割的,就不符合一範式。
不過能不能分割並沒有絕對的答案,看需求,也就是看你的設計目標而定。
舉例:
學生信息組成學生信息表,有姓名、年齡、性別、學號等信息組成。
姓名不可拆分吧?所以可以作爲該表的一個字段。
但我要說這個表要在國外使用呢?人家姓和名要分開,都有特別的意義,所以姓名字段是可拆分的,分爲姓字段和名字段。
簡單來說,一範式是關係數據庫的基礎,但字段是否真的不可拆分,根據你的設計目標而定。


二範式就是要有主鍵,要求其他字段都依賴於主鍵。
爲什麼要有主鍵?沒有主鍵就沒有唯一性,沒有唯一性在集合中就定位不到這行記錄,所以要主鍵。
其他字段爲什麼要依賴於主鍵?因爲不依賴於主鍵,就找不到他們。更重要的是,其他字段組成的這行記錄和主鍵表示的是同一個東西,而主鍵是唯一的,它們只需要依賴於主鍵,也就成了唯一的。
如果有同學不理解依賴這個詞,可以勉強用“相關”這個詞代替,也就是說其他字段必須和它們的主鍵相關。因爲不相關的東西不應該放在一行記錄裏。
舉例:
學生信息組成學生表,姓名可以做主鍵麼?
不能!因爲同名的話,就不唯一了,所以需要學號這樣的唯一編碼才行。
那麼其他字段依賴於主鍵是什麼意思?
就是“張三”同學的年齡和性別等字段,不能存儲別人的年齡性別,必須是他自己的,因爲張三的學號信息就決定了,這行記錄歸張三所有,不能給無關人員使用。


三範式就是要消除傳遞依賴,方便理解,可以看做是“消除冗餘”。
消除冗餘應該比較好理解一些,就是各種信息只在一個地方存儲,不出現在多張表中。
比如說大學分了很多系(中文系、英語系、計算機系……),這個系別管理表信息有以下字段組成:
系編號,系主任,系簡介,系架構。
那麼再回到學生信息表,張三同學的年齡、性別、學號都有了,我能不能把他的系編號,系主任、系簡介也一起存着?
如果你問三範式,當然不行,因爲三範式不同意。
因爲系編號,系主任、系簡介已經存在系別管理表中,你再存入學生信息表,就是冗餘了。
三範式中說的傳遞依賴,就出現了。
這個時候學生信息表中,系主任信息是不是依賴於系編號了?而這個表的主鍵可是學號啊!
所以按照三範式,處理這個問題的時候,學生表就只能增加一個系編號字段。
這樣既能根據系編號找到系別信息,又避免了冗餘存儲的問題。
 

2.髒讀&不可重複讀&幻讀

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

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

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

不可重複讀&幻讀區別:

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

不可重複讀重點在於update和delete,而幻讀的重點在於insert。如何通過鎖機制來解決他們產生的問題。

==============================================================================================

3.索引(-----------------------------)

數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用 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的特性而頻繁的分裂調整,十分低效,建議使用自增字段作爲主鍵。

4.mysql鎖機制  

MySQL數據庫(InnoDB引擎)默認

樂觀鎖
樂觀鎖不是數據庫自帶的,需要我們自己去實現。樂觀鎖是指操作數據庫時(更新操作),想法很樂觀,認爲這次的操作不會導致衝突,在操作數據時,並不進行任何其他的特殊處理(也就是不加鎖),而在進行更新後,再去判斷是否有衝突了。

通常實現是這樣的:在表中的數據進行操作時(更新),先給數據表加一個版本(version)字段,每操作一次,將那條記錄的版本號加1。也就是先查詢出那條記錄,獲取出version字段,如果要對那條記錄進行操作(更新),則先判斷此刻version的值是否與剛剛查詢出來時的version的值相等,如果相等,則說明這段期間,沒有其他程序對其進行操作,則可以執行更新,將version字段的值加1;如果更新時發現此刻的version值與剛剛獲取出來的version的值不相等,則說明這段期間已經有其他程序對其進行操作了,則不進行更新操作。

舉例:

下單操作包括3步驟:

1.查詢出商品信息

select (status,status,version) from t_goods where id=#{id}

2.根據商品信息生成訂單

3.修改商品status爲2

update t_goods 

set status=2,version=version+1

where id=#{id} and version=#{version};

除了自己手動實現樂觀鎖之外,現在網上許多框架已經封裝好了樂觀鎖的實現,如hibernate

悲觀鎖

與樂觀鎖相對應的就是悲觀鎖了。悲觀鎖就是在操作數據時,認爲此操作會出現數據衝突,所以在進行每次操作時都要通過獲取鎖才能進行對相同數據的操作,這點跟java中的synchronized很相似,所以悲觀鎖需要耗費較多的時間。另外與樂觀鎖相對應的,悲觀鎖是由數據庫自己實現了的,要用的時候,我們直接調用數據庫的相關語句就可以了。

參照:https://blog.csdn.net/puhaiyang/article/details/72284702

 

 

 

 

發佈了21 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章