你好,面試官 | 我可以憑借MySQL架構體系,事務鎖機制原理進你公司嗎???
面試現場
叮叮叮......
面試官:“你好,我是XX面試官,請問是小龍嗎?”
小龍:“您好,面試官,我是小龍”
面試官:“好的,現在有空嗎,我們開始面試吧”
小龍:“嗯嗯,準備好啦”
.......
other questions
.......
面試官:“好的,我們先根據你簡歷聊聊哈,我看你有提到熟悉 MySQL的使用嗎 ?。”
小龍:“哈哈,還算可以吧!”
面試官:“那你能告訴我 MySQL 大體的一個架構是怎樣的嗎?有去了解過嗎?”
小龍:“MySQL 分為 Server 層與 存儲引擎層,Server 層包含連接器、分析器、優化器、執行器。”
面試官:“那現在假如我執行一條 SQL 語句 select name from xl_tb where 主鍵ID=1,你覺得 MySQL 底層是怎樣去解析執行這條 SQL 的呢?”
小龍:“首先要由我們的客戶端去連接服務器,需要連接器進行身份驗證,權限認證。”
小龍:“然后在MySQL8.0之前,如果開啟了緩存,執行這條 SQL 的話會首先以這條 SQL 為 key 去緩存查詢是否有對應的 value,如果有直接返回結果,MySQL8.0 在綜合考慮其優劣后移除了緩存。”
面試官:“嗯嗯,那假如沒有開啟緩存,或者沒有該 SQL 映射的結果呢?”
小龍:“那么便會正式解析這條 SQL 去查詢結果啦。”
面試官:“能簡單說說是怎樣解析 SQL 的嗎?”
小龍:“服務器肯定不會什么語句都給你去執行一遍,首先它會利用分析器通過詞法語法分析看這條語句是否符合它的語法規則,并解析關鍵詞等”
小龍:“如果語法沒問題,也不能就這么拿去執行了,因為要考慮執行代價成本之類的。”
面試官:“那它內部是怎么做的呢?”
小龍:“MySQL 會通過優化器生成該 SQL語句的執行計劃,我們可以通過 explain 命令查詢。然后若你用到了索引可能還會選擇索引,它會選擇最優的方案去執行,因為即使你使用了索引,在某些情況可能也沒有全表掃描來的快。”
小龍:“這里,肯定就走主鍵索引,根據 ID=1 去查。”
面試官:“enen,那得到最優執行方案后,最后是怎樣執行的呢?”
小龍:“最后語句來到執行器,打開表調用存儲引擎接口,逐行判斷是否滿足查詢條件,當然如果用到索引,會根據索引來篩選,速度也會更快,這里便是利用主鍵索引去查詢 ID=1 的結果。”
小龍:“然后把滿足條件的放到結果集,最后返給客戶端顯示。”
面試官:“嗯嗯,理解的還是很清楚。OK,知道 MySQL 事務的四大特性嗎?”
獨白:“這個就很基礎。”
小龍:“ ACID,原子性,隔離性,持久性,一致性”
面試官:“OK,那你知道它們底層是怎樣實現的嗎,隨便挑兩個講講?”
獨白:“這個在我【面試筆記】中詳細總結過啦,隨便給面試官舉幾個吧。”
小龍:“比如原子性吧,我們知道實現原子性的關鍵是,事務回滾時能夠撤銷所有已經成功執行的 SQL 語句。”
小龍:“而當事務對數據庫進行修改時,InnoDB 會生成對應的 undo log,undo log 會保存事務開始前老版本的數據,當事務發生異常,便會 rollback 回滾到老版本狀態。”
面試官:“那它是怎樣回滾的呢?”
小龍:“InnoDB 會根據 undo log 的內容做相反邏輯操作,比如:insert 語句,回滾時會執行 delete,update 語句,回滾時便執行相反的 update,把數據改回來。”
小龍:“總之,原子性主要便是靠 undo log 保證 。它是一種回滾日志,不僅可以用來保證原子性,還可以用來實現隔離性 MVCC。”
小龍:”MYSQL的持久性便是由redo log來保證。它可以記錄事務開啟后對數據做的修改,并且可以進行 crash-safe,數據庫異常斷電等情況可用 redo log恢復。“
面試官:“你知道這里面用到的一種 WAL 技術嗎?”
小龍:”MySQL 利用的 WAL 技術,全稱是Write-Ahead Logging 。關鍵點就是先寫日志,再寫磁盤。“
小龍:“可以把 redo log 比作一個卸貨的小推車,我們卸貨若是每下一件物品就拿著去入庫,那豈不是特浪費時間(效率低、還要找到合適存庫位置)”
小龍:“此時,若有一個小推車,我們將貨物首先存放在小推車,當推車滿了再往庫里存,豈不大大增加了效率。”
小龍:“我們在更新數據庫時,就是先將更新操作記錄在redo log日志,等 redo log 滿了或則 MYSQL 空閑了再刷盤。”
獨白:“由于篇幅原因,這里沒有詳細歸納總結,有興趣的可以看【面試筆記】,里面對相關核心重點大廠常考的都詳細總結啦。”
面試官:“OK,由于時間原因,這塊我們就聊到這,你知道事務中存在的一些并發問題嗎?”
小龍:“理論上會存在臟讀、不可重復讀、幻讀,但是可以通過使用不同隔離級別就行控制的。”
面試官:“能給我講講什么是幻讀嗎?”
小龍:“舉個簡單例子,比如事務A 按照一定條件進行數據讀取, 期間事務B 插入了相同搜索條件的新數據,事務A再次按照原先條件進行讀取時,發現了事務B 新插入的數據 稱為幻讀。”
面試官:“那你能告訴我MySQL 是怎樣去解決幻讀的嗎?或者根本就還沒解決,談談你的理解?”
獨白:“由于篇幅原因,這里只做簡單總結,有興趣的可以看【面試筆記】,通過實驗詳細進行了分析,可以幫助更好的理解。”
友情提示:不要相信網上眾說紛紜的帖子,你抄我我抄你,一會這個說RR隔離級別徹底解決了幻讀,一會那個說沒有。最好自己親自做實驗看看,結果一目了然。
我當時為了這個困惑,百度都查爛了,帖子滿天飛,答案混淆視聽,最后干脆自己做實驗最后得出正確結論,并詳細記錄在【面試筆記】中。
小龍:“RR隔離界別并沒有完全解決幻讀,只使用快照讀(使用MVCC解決了幻讀)或則當前讀(間隙鎖解決幻讀)不會幻讀。若先快照讀,然后當前讀,期間按快照讀相同條件插入數據,當前讀就又會發生幻讀。
當時秋招網易云二面,我清楚記得我憑借這個問題徹底征服了面試官,從頭到位給他清楚分析了一遍,最后即使我二本也拿了SP,不過拒了。
面試官:“真的不錯,順便問一下,你能簡單說說隔離級別機制實現原理嗎?”
可能有些同學會說這些不會問,但是很多面試都會拐著彎問你這,只是你不知道。
當時我面試時面試官沒有直接這樣問,我是當它問了事務開始我就一步一步留線索讓它順著我拿手的知識問,由于這樣寫文章會很長,我就直接上問題了。
小龍:“在讀未提交下,可以直接讀取數據,并不能解決任何并發問題。”
小龍:“而可串行化,它主要使用鎖,讀加共享鎖,寫加排他鎖,串行執行來實現。”
小龍:“而讀已提交和可重復讀實現原理就是MVCC Read View不同的生成時機。可重復讀只在事務開始時生成一個Read View,之后都用的這個;讀已提交每次執行前都會生成Read View。”
獨白:“這里關于 Read View 就不展開講了,由于篇幅有限。改期再拿出來講。”
面試官:“好的,時間差不多啦,今天暫時聊那么多,下期再談談。”
獨白:“不愧是我,真男人是也!”
本文轉載自微信公眾號「小龍coding」,可以通過以下二維碼關注。轉載本文請聯系小龍coding公眾號。