不知道你們有沒有想過下面這件事?git
咱們平時調用
DELETE
在 MySQL 中刪除的數據都去哪兒了?github
這還用問嗎?固然是被刪除了啊web
那麼這裏又有個新的問題了,若是在 InnoDB 下,多事務併發的狀況下,若是事務A刪除了 id=1
的數據,同時事務B又去讀取 id=1
的數據,若是這條數據真的被刪除了,那 MVCC 拿啥數據返回給用戶呢?數據庫
沒錯,這就須要瞭解一下 MySQL 的多版本併發的原理相關的東西,感興趣的能夠去看我以前寫的這篇文章。微信
因此,實際狀況中,調用了 DELETE
語句刪除的數據並不會真正的被物理刪除,這條數據其實還在那,只不過被打上了一個標記,標記已刪除。併發
這其實跟咱們平常的操做——軟刪除,差很少是一個意思編輯器
在 MySQL 中, UPDATE
和 DELETE
操做本質上是同樣的, 都屬於更新操做,刪除操做只不過是把某行數據中的一個特定的比特位標記爲已刪除,僅此而已。性能
那麼問題又來了,那這些刪除的數據若是一直這麼堆下去,那不遲早把硬盤撐爆?學習
若是都玩兒成這樣了,那 MySQL 還能像如今這樣被大規模的用於生產環境中嗎?那 MySQL 究竟是怎麼玩的?flex
這就須要提到 Purge 操做了。
Purge操做是啥?
Purge 操做纔是真正將數據(已被標記爲已刪除)物理刪除的操做。
Purge 操做針對的數據對象,不只僅是某一行,還有其對應的索引數據和 Undo Log。
好的那麼問題又來了。
問題是,Purge 操做何時會執行呢?實際上,你能夠將執行 Purge 操做的線程(簡稱 Purge 線程)理解成一個後臺週期性執行的線程。
Purge 線程能夠有一個,也能夠有多個,具體的線程數量能夠由 MySQL 的配置項 innodb_purge_threads
來進行配置。固然,我相信你確定不記得在使用 MySQL 的時候配置過這個,由於 innodb_purge_threads
有個默認值,值爲 4
。
InnoDB 會根據 MySQL 中表的數量和 Purge 線程的數量進行分配。
但正是由於有這種特性,Purge 線程的數量才須要根據業務的實際狀況來作調整。舉個例子,假設 DML 操做都集中在某張表,好比表1上...
你先等等,我打斷一下......
什麼叫 DML 操做?總喜歡搞些複雜的名詞...DML(Data Manipulation Language)數據操做語句,實際上就是CRUD增刪改查...
與之相似的概念還有DDL(Data Definition Language)數據定義語句,也就是CREATE
、DROP
和ALTER
等等.
以及DCL(Data Control Language)數據控制語句,也就是GRANT
、REVOKE
等等...
繼續說回來,雖然 Purge 線程的數量是可配置的,可是也不是你想配多少就配多少的。否則你給它幹個 10000
個線程,那不就直接原地 OOM 了嗎?
innodb_purge_threads
的最大值爲 32,並且並非咱們配了 32 InnoDB 就真的會啓動 32 個 Purge 線程,爲啥呢?舉個很簡單的例子,假設此時只有一張表,而後咱們配置了 32 個 Purge 線程。
你看着上面這個圖問問本身,這「河裏」嗎?這樣不只浪費了系統的資源,同時還使得不一樣的 Purge 線程之間發生了數據競爭。不只如此,Purge 線程還可能跟用戶線程產生競爭。
可是當系統中真的有 32 張表的時候,狀況又不同了,一個 Purge 線程對應一張表,線程與線程之間就不會存在數據競爭,而且沒有浪費系統資源,還可以提高執行 Purge 操做的性能。
這就是爲啥 InnoDB 會根據實際狀況來調整 MySQL 中 Purge 線程的數量,因此咱們在配置的時候也要按照實際狀況來設置。
舉個例子,若是你的數據庫中,增刪改 的操做只集中在某幾張表上,則能夠考慮將 innodb_purge_threads
設置的稍微低一點。相反,若是 增刪改 的操做幾乎每張表都有,那麼 innodb_purge_threads
就能夠設置的大一些。
瞭解完 Purge 線程自己以後,咱們就能夠來了解 Purge 線程所針對的對象了。Purge 線程主要清理的對象是 Undo Logs,其次是行記錄。
由於 Undo Log 能夠分爲:
因此更準確的說法是,Purge 線程清理的對象是 Update Undo Log 和 行記錄,由於 Insert Undo Log 會在事務提交以後就會被刪除。
咱們都知道 InnoDB 的 MVCC 的數據來源是一個一個 Undo Log 造成的單鏈表,而 Purge 線程就是用於按期清理 Undo Log 的,而且在清理完 刪除數據所生成的 Undo Log 的時候,就會把對應的行記錄給移除了。
那麼問題又來了,Purge 線程每次會讀取多少條件 Undo Log 記錄呢?
很明顯,它不是看當時的心情來決定取多少條的。它是經過配置項 innodb_purge_batch_size
來控制的,默認是 300。而後InnoDB會將這300條 Undo Log 分給innodb_purge_threads
個 Purge 線程。在清理的過程當中,Purge 線程還會釋放 Undo Log 表空間內的文件。
本篇文章已放到個人 Github github.com/sh-blog 中,歡迎 Star。微信搜索關注【SH的全棧筆記】,回覆【隊列】獲取MQ學習資料,包含基礎概念解析和RocketMQ詳細的源碼解析,持續更新中。
若是你以爲這篇文章對你有幫助,還麻煩點個贊,關個注,分個享,留個言。