mybatisplus执行sql语句_一条更新的SQL语句是如何执行的?
提出問題
UPDATE student SET score = score + 1 WHERE uid = 666; 以上就是一條最簡單的SQL更新語句,想要知道上面這句SQL語句是怎么執行的先要了解MySQL數據庫的邏輯架構。
UPDATE語句也不例外的執行這個流程,先連接數據庫(連接器),然后將SQL語句進行詞法分析,并檢測SQL語法(分析器),然后優化對應的查詢操作(優化器),最后真正的去執行這個語句(執行器)。
具體到上面的UPDATE語句,先取出uid=666的所有行,然后將這些行的score字段的值加1,并寫入內存中。接下來的過程與查詢語句的查詢流程就不一樣了,查詢語句只需要返回查詢結果即可,但是更新語句需要去真的修改數據庫中的數據,所以更新語句相對來講要復雜一些。
說到SQL的更新語句就不得不提到重做日志(redo log) 和歸檔日志(binlog),這兩個日志在MySQL中起到了巨大的作用,這兩個日志的相互配合也是很有意思的設計,接下來就要詳細給大家講下這兩種日志的作用、它們是如何工作的、以及它們之間的相互配合。
redo log
redo log是為了解決crash-safe問題而產生的,是一種物理日志,我們知道數據庫是用來存儲數據的,crash-safe問題對于數據庫來說是非常重要的,在開啟redo log之后MySQL的異常重啟之前提交的數據都不會丟失,這樣就能保證異常crash后數據不會丟失。
redo log是InnoDB引擎層的一種日志,是用來記錄這個頁"做了什么改動"。在MySQL中經常會說道WAL技術,WAL的全稱是Write Ahead Logging,WAL的核心思想就是日志先行,舉個例子,執行一條更新語句,InnoDB就會先把記錄寫到redo log里面,然后更新到內存,等到系統比較空閑的時候再寫入磁盤。redo log的文件大小是固定的,是通過循環寫的 實現的。
有了redo log就能保證InnoDB即使發生異常重啟也不會丟失數據,這種能力也叫做crash-safe的能力
binlog
binlog是一種邏輯日志,是Server層的一種日志,記錄了所有的sql語句,主要是用來配合備份來恢復數據庫的,只要我們有最近一次的備份和這期間完整的binlog就能夠恢復數據庫了。 下面我們來簡單看下binlog文件,我是ubuntu系統,這個文件是放在/var/log/mysql/文件夾下面的,
從上面的圖片我們能看到文件名字是依次增加的,與redo log的循環寫不同,binlog是追加寫的。 我們執行下面的命令行就能看到binlog記錄的sql語句是什么樣的,還有一些binlog文件內容的參照 官方文檔操作。
sudo mysqlbinlog /var/log/mysql/mysql-bin.000002 --base64-output=DECODE-ROWS --verbose —verbose復制代碼執行的結果如下圖所示:
從上圖來看很清晰的能看懂這個update語句執行的含義。
上面講了這么多這兩種日志的含義,下面簡單總結下這兩種日志的一些區別:
- redo log是一種物理日志,記錄是這個頁做了什么改動,而binlog是邏輯日志,記錄是sql語句的原始邏輯。
- redo log的文件大小是固定的,會循環寫入文件,所以會覆蓋之前的日志。而binlog是追加寫,不會覆蓋之前的日志。
- redo log是InnoDB引擎層的日志,而binlog是server層的日志。
有同學會問,為什么要搞兩個日志呀?
我們知道MySQL最開始默認的引擎是MyASIM引擎,根本就不存在crash-safe的問題,binlog只是用來做歸檔的。在MySQL5.5.5之后將InnoDB作為默認的存儲引擎,這樣InnoDB就擁有了crash-safe的能力,在MySQL的架構中,引擎是以插件的形式存在的,InnoDB引擎不是MySQL數據庫必須的,所以也就好理解redo log也不是MySQL數據庫必須的日志。
這也就好理解為什么要搞兩個日志,一個是server層,一個是引擎層,他們負責不同的功能,相互合作。
那具體這兩個日志是怎么合作的呢?他們怎么保證數據的一致性呢?
兩階段提交
先說下兩階段提交的具體過程:
- UPDATE語句的結果寫入內存,同時將這個操作寫入redo log,此時redo log處于prepare狀態,并告知執行器隨時可以提交事物。
- 執行器生成這個操作的binlog,并寫入binlog日志。
- 執行器通知將之前處于prepare狀態改為commit狀態,更新完成。
兩個階段提交保證了redo log和binlog的一致性。 下面來分析下如果不是兩個階段提交會發生什么?
先寫redo log后寫binlog
如果先寫redo log再寫binlog的話,當redo log寫完的時候發生了crash,此時binlog里面是沒有記錄的。這時候發生重啟,redo log會恢復crash的語句,但是如果用這產生時的binlog去恢復數據庫就會丟失這條記錄,此時兩個日志恢復的數據庫數據就產生了差異。
先寫binlog后寫redo log
如果是先寫binlog后寫redo log,當寫完binlog的時候發生了crash。這時候發生重啟,redo log中還沒寫,此時異常重啟后這個事務是無效的,所以無法恢復,但是binlog中有這條數據,當用此時的binlog文件去恢復數據庫的時候,就會比當前的數據庫數據多一條記錄。
從上面就可以明白,如果不用兩階段提交就有可能出現兩個日志狀態不一致。
總結
以上是生活随笔為你收集整理的mybatisplus执行sql语句_一条更新的SQL语句是如何执行的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小天才z2s和z5区别(古代小字与小名的
- 下一篇: mysql 单表字段多少合适_复制信息记