超乾貨!爲了讓你完全弄懂MySQL事務日誌,我通宵肝出了這份圖解!

還記得剛上研究生的時候,導師常掛在嘴邊的一句話,「科研的基礎不過就是數據而已。」現在看來,不管是人文社科,仍是天然科學,或許均可在必定程度上看做是數據的科學。html

假若剝開研究領域的外衣,將人的操做抽象出來,那麼科研的過程大概就是根據數據流動探索其中的未知信息吧。固然科學研究的範疇涵蓋甚廣,也不是一兩句話可以拎得清的。不過從這個角度上的闡述,也只是爲了引出數據的重要性。mysql

在當今社會,充斥着大量的數據。從衆多APP上的帳戶資料到銀行信用體系等我的檔案,都離不開對大量數據的組織、存儲和管理。而這,即是數據庫存在的目的和價值。程序員

目前數據庫的類型主要分爲兩種,一種是關係型數據庫,另外一種是非關係型數據庫(NoSQL)。而咱們今天的主角MySQL就是關係型數據庫中的一種。面試

本文結構

1 關係型數據庫與NoSQL

關係型數據庫,顧名思義,是指存儲的數據之間具備關係。這種所謂的關係一般用二維表格中的行列來表示,即一個二維表的邏輯結構可以反映表中數據的存儲關係。redis

概念老是拗口難懂的。那麼簡單來講,關係型數據庫的存儲就是按照表格進行的。數據的存儲實際上就是對一個或者多個表格的存儲。經過對這些表格進行分類、合併、鏈接或者選取等運算來實現對數據庫的管理。常見的關係型數據庫有MySQL、Oracle、DB2和SqlServer等。算法

非關係型數據庫(NoSQL)是相對於關係型數據庫的一種泛指,它的特色是去掉了關係型數據庫中的關係特性,從而可得到更好的擴展性。NoSQL並無嚴格的存儲方式,但採用不一樣的存儲結構都是爲了得到更高的性能和更高的併發。NoSQL根據存儲方式可分爲四大類,鍵值存儲數據庫、列存儲數據庫、文檔型數據庫和圖形數據庫。這四種數據的存儲原理不盡相同,於是在應用場景上也有些許的差別。通常經常使用的有做爲數據緩存的redis和分佈式系統的HBase。目前常見的數據庫排名可見網站:sql

https://db-engines.com/en/ranking數據庫

四種NoSQL的特色比較

關係型數據庫與非關係型數據庫本質上的區別就在於存儲的數據是否具備必定的邏輯關係,由此產生的兩類數據庫看的性能和優劣勢上也有必定的區別。兩者對比可見下圖。編程

關係型數據庫與NoSQL的優缺點對比

2 MySQL簡介

介紹

在關係型數據庫中,MySQL能夠說是其中的王者。它是目前最流行的數據庫之一,由瑞典 MySQL AB 公司開發,目前屬於 Oracle 公司。MySQL數據庫具備如下幾個方面的優點:緩存

  • 體積小、速度快;
  • 代碼開源,採用了 GPL 協議,能夠修改源碼來開發本身的 MySQL 系統;
  • 支持大型的數據庫,能夠處理擁有上千萬條記錄的大型數據庫;
  • 使用標準的 SQL 數據語言形式,並採用優化的 SQL 查詢算法,有效地提升查詢速度;
  • 使用 C 和 C++ 編寫,並使用多種編譯器進行測試,保證源代碼的可移植性;
  • 可運行在多個系統上,而且支持多種語言;
  • 核心程序採用徹底的多線程編程,能夠靈活地爲用戶提供服務,充分利用CPU資源。

邏輯架構

MySQL的邏輯架構可分爲四層,包括鏈接層、服務層、引擎層和存儲層,各層的接口交互及做用以下圖所示。須要注意的是,因爲本文將主要講解事務的實現原理,所以下文針對的都是InnoDB引擎下的狀況。

鏈接層:負責處理客戶端的鏈接以及權限的認證。

服務層:定義有許多不一樣的模塊,包括權限判斷,SQL接口,SQL解析,SQL分析優化, 緩存查詢的處理以及部份內置函數執行等。MySQL的查詢語句在服務層內進行解析、優化、緩存以及內置函數的實現和存儲。

引擎層:負責MySQL中數據的存儲和提取。MySQL中的服務器層無論理事務,事務是由存儲引擎實現的。其中使用最爲普遍的存儲引擎爲InnoDB,其它的引擎都不支持事務。

存儲層:負責將數據存儲與設備的文件系統中。

MySQL的邏輯架構

3 MySQL事務

事務是MySQL區別於NoSQL的重要特徵,是保證關係型數據庫數據一致性的關鍵技術。事務可看做是對數據庫操做的基本執行單元,可能包含一個或者多個SQL語句。這些語句在執行時,要麼都執行,要麼都不執行。

事務的執行主要包括兩個操做,提交和回滾。

提交:commit,將事務執行結果寫入數據庫。

回滾:rollback,回滾全部已經執行的語句,返回修改以前的數據。

MySQL事務包含四個特性,號稱ACID四大天王。

原子性(Atomicity) :語句要麼全執行,要麼全不執行,是事務最核心的特性,事務自己就是以原子性來定義的;實現主要基於undo log日誌實現的。

持久性(Durability :保證事務提交後不會由於宕機等緣由致使數據丟失;實現主要基於redo log日誌。

隔離性(Isolation) :保證事務執行儘量不受其餘事務影響;InnoDB默認的隔離級別是RR,RR的實現主要基於鎖機制、數據的隱藏列、undo log和類next-key lock機制。

一致性(Consistency) :事務追求的最終目標,一致性的實現既須要數據庫層面的保障,也須要應用層面的保障。

原子性

事務的原子性就如原子操做通常,表示事務不可再分,其中的操做要麼都作,要麼都不作;若是事務中一個SQL語句執行失敗,則已執行的語句也必須回滾,數據庫退回到事務前的狀態。只有0和1,沒有其它值。

事務的原子性代表事務就是一個總體,當事務沒法成功執行的時候,須要將事務中已經執行過的語句所有回滾,使得數據庫迴歸到最初未開始事務的狀態。

事務的原子性就是經過undo log日誌進行實現的。當事務須要進行回滾時,InnoDB引擎就會調用undo log日誌進行SQL語句的撤銷,實現數據的回滾。

持久性

事務的持久性是指當事務提交以後,數據庫的改變就應該是永久性的,而不是暫時的。這也就是說,當事務提交以後,任何其它操做甚至是系統的宕機故障都不會對原來事務的執行結果產生影響。

事務的持久性是經過InnoDB存儲引擎中的redo log日誌來實現的,具體實現思路見下文。

隔離性

原子性和持久性是單個事務自己層面的性質,而隔離性是指事務之間應該保持的關係。隔離性要求不一樣事務之間的影響是互不干擾的,一個事務的操做與其它事務是相互隔離的。

因爲事務可能並不僅包含一條SQL語句,因此在事務的執行期間頗有可能會有其它事務開始執行。所以多事務的併發性就要求事務之間的操做是相互隔離的。這一點跟多線程之間數據同步的概念有些相似。

鎖機制

事務之間的隔離,是經過鎖機制實現的。當一個事務須要對數據庫中的某行數據進行修改時,須要先給數據加鎖;加了鎖的數據,其它事務是不運行操做的,只能等待當前事務提交或回滾將鎖釋放。

鎖機制並非一個陌生的概念,在許多場景中都會利用到不一樣實現的鎖對數據進行保護和同步。而在MySQL中,根據不一樣的劃分標準,還可將鎖分爲不一樣的種類。

按照粒度劃分:行鎖、表鎖、頁鎖

按照使用方式劃分:共享鎖、排它鎖

按照思想劃分:悲觀鎖、樂觀鎖

鎖機制的知識點不少,因爲篇幅很差所有展開講。這裏對按照粒度劃分的鎖進行簡單介紹。

粒度:指數據倉庫的數據單位中保存數據的細化或綜合程度的級別。細化程度越高,粒度級就越小;相反,細化程度越低,粒度級就越大。

MySQL按照鎖的粒度劃分能夠分爲行鎖、表鎖和頁鎖。

行鎖:粒度最小的鎖,表示只針對當前操做的行進行加鎖;

表鎖:粒度最大的鎖,表示當前的操做對整張表加鎖;

頁鎖:粒度介於行級鎖和表級鎖中間的一種鎖,表示對頁進行加鎖。

數據庫的粒度劃分

這三種鎖是在不一樣層次上對數據進行鎖定,因爲粒度的不一樣,其帶來的好處和劣勢也不一而同。

表鎖在操做數據時會鎖定整張表,於是併發性能較差;

行鎖則只鎖定須要操做的數據,併發性能好。可是因爲加鎖自己須要消耗資源(得到鎖、檢查鎖、釋放鎖等都須要消耗資源),所以在鎖定數據較多狀況下使用表鎖能夠節省大量資源。

MySQL中不一樣的存儲引擎可以支持的鎖也是不同的。MyIsam只支持表鎖,而InnoDB同時支持表鎖和行鎖,且出於性能考慮,絕大多數狀況下使用的都是行鎖。

併發讀寫問題

在併發狀況下,MySQL的同時讀寫可能會致使三類問題,髒讀、不可重複度和幻讀。

(1)髒讀:當前事務中讀到其餘事務未提交的數據,也就是髒數據。

以上圖爲例,事務A在讀取文章的閱讀量時,讀取到了事務B爲提交的數據。若是事務B最後沒有順利提交,致使事務回滾,那麼實際上閱讀量並無修改爲功,而事務A倒是讀到的修改後的值,顯然不合情理。

(2)不可重複讀:在事務A中前後兩次讀取同一個數據,可是兩次讀取的結果不同。髒讀與不可重複讀的區別在於:前者讀到的是其餘事務未提交的數據,後者讀到的是其餘事務已提交的數據。

以上圖爲例,事務A在前後讀取文章閱讀量的數據時,結果卻不同。說明事務A在執行的過程當中,閱讀量的值被其它事務給修改了。這樣使得數據的查詢結果再也不可靠,一樣也不合實際。

(3)幻讀:在事務A中按照某個條件前後兩次查詢數據庫,兩次查詢結果的行數不一樣,這種現象稱爲幻讀。不可重複讀與幻讀的區別能夠通俗的理解爲:前者是數據變了,後者是數據的行數變了。

以上圖爲例,當對0<閱讀量<100的文章進行查詢時,先查到了一個結果,後來查詢到了兩個結果。這代表同一個事務的查詢結果數不一,行數不一致。這樣的問題使得在根據某些條件對數據篩選的時候,先後篩選結果不具備可靠性。

隔離級別

根據上面這三種問題,產生了四種隔離級別,代表數據庫不一樣程度的隔離性質。

在實際的數據庫設計中,隔離級別越高,致使數據庫的併發效率會越低;而隔離級別過低,又會致使數據庫在讀寫過程當中會遇到各類亂七八糟的問題。

所以在大多數數據庫系統中,默認的隔離級別時讀已提交(如Oracle)或者可重複讀RR(MySQL的InnoDB引擎)。

MVCC

又是一個難嚼的大塊頭。MVCC就是用來實現上面的第三個隔離級別,可重複讀RR。

MVCC:Multi-Version Concurrency Control,即多版本的併發控制協議。

MVCC的特色就是在同一時刻,不一樣事務能夠讀取到不一樣版本的數據,從而能夠解決髒讀和不可重複讀的問題。

MVCC實際上就是經過數據的隱藏列和回滾日誌(undo log),實現多個版本數據的共存。這樣的好處是,使用MVCC進行讀數據的時候,不用加鎖,從而避免了同時讀寫的衝突。

在實現MVCC時,每一行的數據中會額外保存幾個隱藏的列,好比當前行建立時的版本號和刪除時間和指向undo log的回滾指針。這裏的版本號並非實際的時間值,而是系統版本號。每開始新的事務,系統版本號都會自動遞增。事務開始時的系統版本號會做爲事務的版本號,用來和查詢每行記錄的版本號進行比較。

每一個事務又有本身的版本號,這樣事務內執行數據操做時,就經過版本號的比較來達到數據版本控制的目的。

另外,InnoDB實現的隔離級別RR時能夠避免幻讀現象的,這是經過next-key lock機制實現的。這裏簡單講講吧。

next-key lock實際上就是行鎖的一種,只不過它不僅是會鎖住當前行記錄的自己,還會鎖定一個範圍。好比上面幻讀的例子,開始查詢0<閱讀量<100的文章時,只查到了一個結果。next-key lock會將查詢出的這一行進行鎖定,同時還會對0<閱讀量<100這個範圍進行加鎖,這其實是一種間隙鎖。間隙鎖可以防止其餘事務在這個間隙修改或者插入記錄。這樣一來,就保證了在0<閱讀量<100這個間隙中,只存在原來的一行數據,從而避免了幻讀。

間隙鎖:封鎖索引記錄中的間隔

雖然InnoDB使用next-key lock可以避免幻讀問題,但卻並非真正的可串行化隔離。再來看一個例子吧。

首先提一個問題,在T6事務A提交事務以後,猜一猜文章A和文章B的閱讀量爲多少?

答案是,文章AB的閱讀量都被修改爲了10000。這表明着事務B的提交實際上對事務A的執行產生了影響,代表兩個事務之間並非徹底隔離的。雖然可以避免幻讀現象,可是卻沒有達到可串行化的級別。

這還說明,避免髒讀、不可重複讀和幻讀,是達到可串行化的隔離級別的必要不充分條件。可串行化是都可以避免髒讀、不可重複讀和幻讀,可是避免髒讀、不可重複讀和幻讀卻不必定達到了可串行化。

一致性

一致性是指事務執行結束後,數據庫的完整性約束沒有被破壞,事務執行的先後都是合法的數據狀態。

一致性是事務追求的最終目標:前面提到的原子性、持久性和隔離性,都是爲了保證數據庫狀態的一致性。

這就很少說了吧。你細品。

4 MySQL日誌系統

瞭解完MySQL的基本架構,大致上可以對MySQL的執行流程有了比較清晰的認知。接下來我將在講述MySQL事務以前,先爲你們介紹如下日誌系統,以方便以後更好的理解事務的特性和實現。

MySQL日誌系統是數據庫的重要組件,用於記錄數據庫的更新和修改。若數據庫發生故障,可經過不一樣日誌記錄恢復數據庫的原來數據。所以實際上日誌系統直接決定着MySQL運行的魯棒性和穩健性。

MySQL的日誌有不少種,如二進制日誌(binlog)、錯誤日誌、查詢日誌、慢查詢日誌等,此外InnoDB存儲引擎還提供了兩種日誌:redo log(重作日誌)和undo log(回滾日誌)。這裏將重點針對InnoDB引擎,對重作日誌、回滾日誌和二進制日誌這三種進行分析。

重作日誌(redo log)

重作日誌(redo log)是InnoDB引擎層的日誌,用來記錄事務操做引發數據的變化,記錄的是數據頁的物理修改。

重作日記的做用其實很好理解,我打個比方。數據庫中數據的修改就比如你寫的論文,萬一哪天論文丟了怎麼呢?以防這種不幸的發生,咱們能夠在寫論文的時候,每一次修改都拿個小本本記錄一下,記錄什麼時間對某一頁進行了怎麼樣的修改。這就是重作日誌。

InnoDB引擎對數據的更新,是先將更新記錄寫入redo log日誌,而後會在系統空閒的時候或者是按照設定的更新策略再將日誌中的內容更新到磁盤之中。這就是所謂的預寫式技術(Write Ahead logging)。這種技術能夠大大減小IO操做的頻率,提高數據刷新的效率。

髒數據刷盤

值得注意的是,redo log日誌的大小是固定的,爲了可以持續不斷的對更新記錄進行寫入,在redo log日誌中設置了兩個標誌位置,checkpointwrite_pos,分別表示記錄擦除的位置和記錄寫入的位置。redo log日誌的數據寫入示意圖可見下圖。

write_pos標誌到了日誌結尾時,會從結尾跳至日誌頭部進行從新循環寫入。因此redo log的邏輯結構並非線性的,而是可看做一個圓周運動。write_poscheckpoint中間的空間可用於寫入新數據,寫入和擦除都是日後推移,循環往復的。

write_pos追上checkpoint時,表示redo log日誌已經寫滿。這時不能繼續執行新的數據庫更新語句,須要停下來先刪除一些記錄,執行checkpoint規則騰出可寫空間。

checkpoint規則:checkpoint觸發後,將buffer中髒數據頁和髒日誌頁都刷到磁盤。

髒數據:指內存中未刷到磁盤的數據。

redo log中最重要的概念就是緩衝池buffer pool,這是在內存中分配的一個區域,包含了磁盤中部分數據頁的映射,做爲訪問數據庫的緩衝。

當請求讀取數據時,會先判斷是否在緩衝池命中,若是未命中才會在磁盤上進行檢索後放入緩衝池;

當請求寫入數據時,會先寫入緩衝池,緩衝池中修改的數據會按期刷新到磁盤中。這一過程也被稱之爲刷髒

所以,當數據修改時,除了修改buffer pool中的數據,還會在redo log中記錄此次操做;當事務提交時,會根據redo log的記錄對數據進行刷盤。若是MySQL宕機,重啓時能夠讀取redo log中的數據,對數據庫進行恢復,從而保證了事務的持久性,使得數據庫得到crash-safe能力。

髒日誌刷盤

除了上面提到的對於髒數據的刷盤,實際上redo log日誌在記錄時,爲了保證日誌文件的持久化,也須要經歷將日誌記錄從內存寫入到磁盤的過程。redo log日誌可分爲兩個部分,一是存在易失性內存中的緩存日誌redo log buff,二是保存在磁盤上的redo log日誌文件redo log file

爲了確保每次記錄都可以寫入到磁盤中的日誌中,每次將redo log buffer中的日誌寫入redo log file的過程當中都會調用一次操做系統的fsync操做。

fsync函數:包含在UNIX系統頭文件#include <unistd.h>中,用於同步內存中全部已修改的文件數據到儲存設備。

在寫入的過程當中,還須要通過操做系統內核空間的os buffer。redo log日誌的寫入過程可見下圖。

redo log日誌刷盤流程

二進制日誌(binlog)

二進制日誌binlog是服務層的日誌,還被稱爲歸檔日誌。binlog主要記錄數據庫的變化狀況,內容包括數據庫全部的更新操做。全部涉及數據變更的操做,都要記錄進二進制日誌中。所以有了binlog能夠很方便的對數據進行復制和備份,於是也經常使用做主從庫的同步。

這裏binlog所存儲的內容看起來彷佛與redo log很類似,可是其實否則。redo log是一種物理日誌,記錄的是實際上對某個數據進行了怎麼樣的修改;而binlog是邏輯日誌,記錄的是SQL語句的原始邏輯,好比」給ID=2這一行的a字段加1 "。binlog日誌中的內容是二進制的,根據日記格式參數的不一樣,可能基於SQL語句、基於數據自己或者兩者的混合。通常經常使用記錄的都是SQL語句。

這裏的物理和邏輯的概念,個人我的理解是:

物理的日誌可看做是實際數據庫中數據頁上的變化信息,只看重結果,而不在意是經過「何種途徑」致使了這種結果;

邏輯的日誌可看做是經過了某一種方法或者操做手段致使數據發生了變化,存儲的是邏輯性的操做。

同時,redo log是基於crash recovery,保證MySQL宕機後的數據恢復;而binlog是基於point-in-time recovery,保證服務器能夠基於時間點對數據進行恢復,或者對數據進行備份。

事實上最開始MySQL是沒有redo log日誌的。由於起先MySQL是沒有InnoDB引擎的,自帶的引擎是MyISAM。binlog是服務層的日誌,所以全部引擎都可以使用。可是光靠binlog日誌只能提供歸檔的做用,沒法提供crash-safe能力,因此InnoDB引擎就採用了學自於Oracle的技術,也就是redo log,這才擁有了crash-safe能力。這裏對redo log日誌和binlog日誌的特色分別進行了對比:

redo log與binlog的特色比較

在MySQL執行更新語句時,都會涉及到redo log日誌和binlog日誌的讀寫。一條更新語句的執行過程以下:

MySQL更新語句的執行過程

從上圖能夠看出,MySQL在執行更新語句的時候,在服務層進行語句的解析和執行,在引擎層進行數據的提取和存儲;同時在服務層對binlog進行寫入,在InnoDB內進行redo log的寫入。

不只如此,在對redo log寫入時有兩個階段的提交,一是binlog寫入以前prepare狀態的寫入,二是binlog寫入以後commit狀態的寫入。

之因此要安排這麼一個兩階段提交,天然是有它的道理的。如今咱們能夠假設不採用兩階段提交的方式,而是採用「單階段」進行提交,即要麼先寫入redo log,後寫入binlog;要麼先寫入binlog,後寫入redo log。這兩種方式的提交都會致使原先數據庫的狀態和被恢復後的數據庫的狀態不一致。

先寫入redo log,後寫入binlog:

在寫完redo log以後,數據此時具備crash-safe能力,所以系統崩潰,數據會恢復成事務開始以前的狀態。可是,若在redo log寫完時候,binlog寫入以前,系統發生了宕機。此時binlog沒有對上面的更新語句進行保存,致使當使用binlog進行數據庫的備份或者恢復時,就少了上述的更新語句。從而使得id=2這一行的數據沒有被更新。

先寫redo log後寫binlog的問題

先寫入binlog,後寫入redo log:

寫完binlog以後,全部的語句都被保存,因此經過binlog複製或恢復出來的數據庫中id=2這一行的數據會被更新爲a=1。可是若是在redo log寫入以前,系統崩潰,那麼redo log中記錄的這個事務會無效,致使實際數據庫中id=2這一行的數據並無更新。

先寫binlog後寫redo log的問題

因而可知,兩階段的提交就是爲了不上述的問題,使得binlog和redo log中保存的信息是一致的。

回滾日誌(undo log)

回滾日誌一樣也是InnoDB引擎提供的日誌,顧名思義,回滾日誌的做用就是對數據進行回滾。當事務對數據庫進行修改,InnoDB引擎不只會記錄redo log,還會生成對應的undo log日誌;若是事務執行失敗或調用了rollback,致使事務須要回滾,就能夠利用undo log中的信息將數據回滾到修改以前的樣子。

可是undo log不redo log不同,它屬於邏輯日誌。它對SQL語句執行相關的信息進行記錄。當發生回滾時,InnoDB引擎會根據undo log日誌中的記錄作與以前相反的工做。好比對於每一個數據插入操做(insert),回滾時會執行數據刪除操做(delete);對於每一個數據刪除操做(delete),回滾時會執行數據插入操做(insert);對於每一個數據更新操做(update),回滾時會執行一個相反的數據更新操做(update),把數據改回去。undo log由兩個做用,一是提供回滾,二是實現MVCC。

5 主從複製

主從複製的概念很簡單,就是從原來的數據庫複製一個徹底同樣的數據庫,原來的數據庫稱做主數據庫,複製的數據庫稱爲從數據庫。從數據庫會與主數據庫進行數據同步,保持兩者的數據一致性。

主從複製的原理實際上就是經過bin log日誌實現的。bin log日誌中保存了數據庫中全部SQL語句,經過對bin log日誌中SQL的複製,而後再進行語句的執行便可實現從數據庫與主數據庫的同步。

主從複製的過程可見下圖。主從複製的過程主要是靠三個線程進行的,一個運行在主服務器中的發送線程,用於發送binlog日誌到從服務器。兩外兩個運行在從服務器上的I/O線程和SQL線程。I/O線程用於讀取主服務器發送過來的binlog日誌內容,並拷貝到本地的中繼日誌中。SQL線程用於讀取中繼日誌中關於數據更新的SQL語句並執行,從而實現主從庫的數據一致。

主從複製原理

之因此須要實現主從複製,其實是由實際應用場景所決定的。主從複製可以帶來的好處有:

1 經過複製實現數據的異地備份,當主數據庫故障時,可切換從數據庫,避免數據丟失。

2 可實現架構的擴展,當業務量愈來愈大,I/O訪問頻率太高時,採用多庫的存儲,能夠下降磁盤I/O訪問的頻率,提升單個機器的I/O性能。

3 可實現讀寫分離,使數據庫能支持更大的併發。

4 實現服務器的負載均衡,經過在主服務器和從服務器之間切分處理客戶查詢的負荷。

6 總結

MySQL數據庫應該算是程序員必須掌握的技術之一了。不管是項目過程當中仍是面試中,MySQL都是很是重要的基礎知識。不過,對於MySQL來講,真的東西太多了。我在寫這篇文章的時候,查閱了大量的資料,發現越看不懂的越多。還真是應了那句話:

你知道的越多,不知道的也就越多。

這篇文章着重是從理論的角度去解析MySQL基本的事務和日誌系統的基本原理,我在表述的時候儘量的避免採用實際的代碼去描述。即使是這篇將近一萬字+近二十副純手工繪製的圖解,也難以將MySQL的博大精深分析透徹。

可是我相信,對於初學者而言,這些理論可以讓你對MySQL有一個總體的感知,讓你對「何謂關係型數據庫」這麼一個問題有了比較清晰的認知;而對於熟練掌握MySQL的大佬來講,或許本文也可以喚醒你塵封已久的底層理論基礎,對你以後的面試也會有必定幫助。

技術這種東西沒有絕對的對錯,假若文中有誤還請諒解,並歡迎與我討論。自主思考永遠比被動接受更有效。

7 reference

http://www.javashuo.com/article/p-sjdijwzs-by.html

https://www.cnblogs.com/ivy-zheng/p/11094528.html

https://blog.csdn.net/qq_39016934/article/details/90116706

https://www.jianshu.com/p/5af73b203f2a

https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html#auto_id_2

微信搜索業餘碼農,閱讀更多技術隨筆。

相關文章
相關標籤/搜索