SQL在MySQL數(shù)據(jù)庫中是如何執(zhí)行的

今天和mysql視頻教程欄目一起看看一條更新語句又是怎么一個執(zhí)行流程。

SQL在MySQL數(shù)據(jù)庫中是如何執(zhí)行的

查詢語句的一套執(zhí)行流程,更新語句也會同樣的走一步,下邊我們在對照上次文章中的圖來簡單的看一下:

SQL在MySQL數(shù)據(jù)庫中是如何執(zhí)行的” class=”lazyload” src=”https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d529960ec1dd496ca90860641bcaa093~tplv-k3u1fbpfcp-watermark.image” data-width=”800″ data- style=”max-width:90%”/>

首先,在執(zhí)行語句前要先連接數(shù)據(jù)庫,這是第一步中連接器的工作,前面我們也說過,當(dāng)一個表有更新的時候,跟這個表有關(guān)的查詢緩存都會失效,所以我們一般不建議十月查詢緩存。

接下來,分析器會經(jīng)過語法分析和詞法分析,知道了這是一條更新語句后,優(yōu)化器決定要使用哪一個索引,然后執(zhí)行器負(fù)責(zé)具體的執(zhí)行,先找到這一行,然后做更新。

與查詢語句更新不同的是,更新流程還涉及兩個重要的日志,這個我們在前邊的文章中也有專門的介紹,有興趣的可以找一下上周的文章《mysql的兩個日志系統(tǒng)》,這里就不多做介紹了。

下邊通過一個簡單的例子來分析一下更新操作的流程。

我們先創(chuàng)建一張表,這個表有主鍵ID和一個整型字段c:

mysql> create table demo T (ID int primarty ,c int);復(fù)制代碼

然后將ID=2的這一行的值加1

mysql> update table demo set c = c + 1 where ID = 2;復(fù)制代碼

接下來我們來看看update語句的執(zhí)行流程,圖中淺色框表示在存儲引擎中執(zhí)行的,神色框代表的是執(zhí)行器中執(zhí)行的。

SQL在MySQL數(shù)據(jù)庫中是如何執(zhí)行的

我們可以看到最后的時候,寫redolog的時候分了兩步,prepare和commit,這就是我們常說的“兩階段提交”。

為什么日志需要“兩階段提交”?

由于redo log和binlog分別是存儲引擎和執(zhí)行器的日志,是兩個獨(dú)立的邏輯,如果不用兩階段提交,無論先提交哪個后提交哪個都會存在一些問題。我們這里也借助上邊的例子看一下,假設(shè)當(dāng)前ID=2的這一行值為0 ,在update的過程中寫完了第一個日志后,第二個日志還沒寫期間發(fā)生了crash,會怎么樣?

  • 先寫redolog后寫binlog。假設(shè)redolog寫完,binlog還沒寫完,MySQL進(jìn)程異常重啟了。我們知道,redolog寫完以后,系統(tǒng)即使崩潰了,也可以將數(shù)據(jù)恢復(fù),所以在MySQL重啟后,這一行回被恢復(fù)成1。由于binlog沒寫完就crash,這時候binlog里面是沒有這個語句的,因此之后備份日志的的時候,存起來的binlog日志也沒有這一條語句。當(dāng)我們需要通過binlog來恢復(fù)數(shù)據(jù)的時候,由于binlog丟失了這條語句,恢復(fù)出來的這一行的值就是0,與原庫的值不一樣啦。
  • 先寫binlog后寫redo log。如果寫完buglog之后,redo log還沒寫完的時候發(fā)生 crash,如果這個時候數(shù)據(jù)庫奔潰了,恢復(fù)以后這個事務(wù)無效,所以這一行的值還是0,但是binlog里已經(jīng)記載了這條更新語句的日志,在以后需要用binlog來恢復(fù)數(shù)據(jù)的時候,就會多了一個事務(wù)出來,執(zhí)行這條更新語句,將值從0更新成1,與原庫中的0就不同了。

我們可以看到如果不使用“兩階段提交”,那么數(shù)據(jù)庫的狀態(tài)就會和用日志恢復(fù)出來的庫不一致。雖然平時用日志恢復(fù)數(shù)據(jù)的概率比較低,但是用日志最多的還是擴(kuò)容的時候,用全量備份和binlog來實(shí)現(xiàn)的,這個時候就可能導(dǎo)致線上的主從數(shù)據(jù)庫不一致的情況。

相關(guān)免費(fèi)學(xué)習(xí)推薦:mysql視頻教程

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊15 分享