以前沒有深究過資料庫底層是怎麼運作的,只是停留在了概念層次,但是後來發現寫程式的時候不是很舒服,總感覺有些點不通,於是決定看看mysql innodb引擎的原理,這裡只是乙個大致的介紹,不會太深入。
如果我們在mysql的客戶端執行了一些個操作,我們不了解任何底層,最簡單的概念模型就是認為資料庫的表裡面的資料被修改了。也就是我這裡執行一次update,資料庫就會執行乙個修改的io操作,很直觀的理解吧?
資料庫當然不會這麼簡單,如果這樣做會有乙個很明顯的效能問題,因為io操作是很慢的,而且資料庫都是cs架構,還要搭上網路層的延遲,如果每一次操作都對應了一次真正的磁碟io,那麼資料庫的效能會大打折扣。那麼怎麼做呢?快取。
mysql innodb引擎有自己的記憶體管理,管理的重點就是日誌和資料塊,先拋開日誌的東西,單說資料塊。mysql的邏輯是,我們任何通過客戶端提交的操作,最終都只在記憶體中進行,不會進行磁碟io,當然如果記憶體沒有還是需要io一次的,但是針對此資料的後續的操作就不需要io了。這樣,我們每一次才做就成了記憶體級別的操作,相比磁碟操作,肯定會快不少。但是這樣也有問題,如果我們改了記憶體中的快取資料,就造成了資料不一致,因為此時同時存在磁碟的資料和記憶體的資料兩個版本,怎麼辦?mysql innodb的做法是,使用一些後台的執行緒來週期性的刷快取的資料到磁碟裡。所以說,我們執行一次更新操作,只會改變記憶體的值,磁碟的值肯定會有延遲。總之,使用快取提高了mysql的處理效率。
那麼剛才說的日誌是什麼回事?日誌主要是與事務相關的,我們知道事務是原子的,要麼不做,要麼全做,這樣才能保持一致性。那如果現在事務做了一半,宕機了,不是違反事務的特性了嗎?這是資料庫產品必須解決的問題。日誌正是幹這個事情的。
每當要做一次操作時,在更新資料前,必須先記錄日誌,只有記錄了日誌,才能更新,因為如果先更新,一旦宕機,那麼這次更新就無法追溯了,我們根本無法得知做了一次更新,如果這次更新只是事務的中間一部分,那麼顯然它需要回滾,我們根本不知道該如何回滾,所以在更新資料前一定要先記錄日誌,這樣才能保證事務的追溯。
同樣的,日誌也有快取,我們每當做一次更新,先把日誌記錄到日誌的快取中,日誌快取也會被週期性的刷回磁碟,不過頻率要更高,innodb是每一秒一次。並且,當執行到commit語句時,會強制把該事務的日誌刷回磁碟,只有事務的commit操作的日誌記錄被刷回磁碟,我們才認為這個事務的commit了的。因為只要我們有日誌了,那麼資料肯定可以重做,不會丟失。那麼有乙個問題,既然commit是乙個關鍵點,為何不等到commit了再把資料和日誌刷回磁碟而非要再起後台的執行緒週期性的刷呢?因為如果事務很長,那麼最後commit時要刷回的東西就會很大,這樣commit的壓力太大,不如提前就刷一部分回去,commit的時候刷的內容就少了,提高了效率。
如果我們正在提交乙個事務t1,然後宕機了,當資料庫再次起起來的時候,資料庫會檢查日誌,看到之前t1事務的日誌,假設沒有commit點,就會認為該事務只執行了一半,那麼所有操作都會被回滾,如果看到了commit,就會認為該事務提交,只需要重做一次日誌即可。
所以,借助了快取技術和日誌,可以實現高效率和事務的功能,雖然這只是乙個概念級別或者巨集觀的理解,但是對於理解資料庫底層的運作還是至關重要的。後面我會深入到細節取研究這些,比如redo undo,mvcc,執行緒的功能等等。
MySql事務概述
事務是訪問並更新資料庫中各種資料項的乙個程式執行單元。在事務中的操作,要麼都執行修改,要麼都不執行,這就是事務的目的,也是事務模型區別於檔案系統的重要特徵之一。嚴格上來說,事務必須同時滿足4個特性,即通常所說事務的acid特性。雖然理論上定義了嚴格的事務要求,但是資料庫廠商出於各種目的並沒有嚴格滿足...
mysql執行原理 mysql 執行原理
闡述mysql系統的各個模組是如何相親相愛的完成乙個我們認為的很簡單的查詢工作的。我們對啟動mysql,客戶端建立連線,請求query,得到返回結果,最終退出。這樣一整個過程來進行分析。第一步 當我們執行啟動mysql系統的命令之後,mysql的初始化模組就從系統配置檔案中讀取系統引數和命令列引數,...
MySQL事務原理
原子性 穩定性和永續性是通過redo 和 undo 日誌檔案實現的,不管是redo還是undo檔案都會有乙個快取我們稱之為redo buf和undo buf。同樣,資料庫檔案也會有快取稱之為data buf。undo記錄了資料在事務開始之前的值,當事務執行失敗或者rollback時可以通過undo記...