1. 程式人生 > 其它 >MySQL中的double write(二)(r12筆記第17天)

MySQL中的double write(二)(r12筆記第17天)

MySQL裡的double write是InnoDB的三大閃亮特性,另外兩個是insert buffer 和自適應雜湊,其實還有幾個比如非同步IO,Flush neighbour Page(重新整理鄰接頁),這個和系統層面的關聯性較高,所以三大亮點還是更有針對性的。

當然一說到MySQL裡的double write,其實主要是要應對一個很自然的問題,那就是partial write。

經典的partial write問題

這個問題比較經典,很多資料庫設計中都需要考慮到這樣一個臨界點的問題,MySQL中的頁是16k,資料的校驗是按照這個為單位進行的,而作業系統層面的資料單位肯定達不到16k,比如是4k,那麼一旦發生斷電的時候,只保留了部分寫入,如果是Oracle DBA一般對此都會很淡定,說用redo來恢復嘛,但是可能我們被遮蔽了一些細節,MySQL在恢復的過程中一個基準是檢查page的checksum,也就是page的最後事務號,發生這種partial page write 的問題時,因為page已經損壞,所以就無法定位到page中的事務號,所以這個時候redo就無法直接恢復。

由此引申一點,partial write的問題在Oracle中肯定也會存在,但是隻是Oracle替我們把這個過程平滑的做好了。其中有設計的差異,還有恢復技術的差別。但是無論如何這個問題都不會繞過去,還得解決。

所以這一類問題,如果討論起來,那可以討論很長時間,可以把體系結構裡的方方面面拿出來分析,做對比。

簡單分析double write問題

對此我畫了一個相對簡陋的圖,也歡迎大家提出改進建議。

總體來說,double write buffer就是一種緩衝快取技術,主要的設計就是為了防止資料在斷電,異常情況下丟失資料。裡面有幾個點需要注意的就是,資料在buffer pool中修改後成了髒頁,這個過程會產生binglog記錄和redo記錄,當然資料寫入資料檔案是一個非同步的工作,如果細看,在共享表空間(system tablespace)中會存在一個2M的空間,分為2個單元,一共128個頁,其中120個用於批量刷髒資料,另外8個用於Single Page Flush。根據阿里同學的分析主要是做區分是因為批量刷髒是後臺執行緒做的,這樣不影響前臺執行緒。而Single page flush是使用者執行緒發起的,需要儘快的刷髒並替換出一個空閒頁出來。所以不是一個嚴格的64+64的拆分。

而資料重新整理的過程,是先使用memcopy把髒資料複製到記憶體中的double write buffer,分兩次寫完,每次寫1MB到共享表空間,然後就是呼叫fsync來同步到磁碟。這裡有一點需要注意的是,這個重新整理到共享表空間的過程,雖然是兩次,但是是順序寫,所以開銷不會很大,也就不會像大家想象的double write效能可能很差,根據Percona的測試,大概也就是5%左右的差別,資料重要還是效能更重要,這是一個基本的命題。當然後續會再寫入對應的表空間檔案中,這個過程就是隨機寫,效能開銷就會大一些。所以在早些時候是用SSD的時候很多人也會帶有如此的顧慮,順序寫還是隨機寫。

當然double write這麼設計就是全面為了作為恢復而用,要不這麼大張旗鼓就不值得了。這個圖來源於 http://blog.csdn.net/renfengjun/article/details/41541809

我覺得已經說得很明白了,就直接引用過來了。

可以看到裡面的一箇中心詞就是checksum,如果出現了partil write的時候,比如斷電,那麼兩次寫的過程中,很可能page是不一致的,這樣checksum校驗就很可能出現問題,而出現問題的時候,因為有了前期寫入共享表空間的頁資訊,所以就可以重構出頁的資訊重新寫入。

double write的另外一個作用

double write其實還有一個特點,就是將資料從double write buffer寫到真正的segment中的時候, 系統會自動合併連線空間重新整理的方式, 這樣一來每次就可以重新整理多個pages,提高效率。

比如下面的環境,我們可以根據show status的結果來得到一個基本的合併頁的情況。

> show status like '%dbl%';  
+----------------------------+----------+
| Variable_name              | Value    |
+----------------------------+----------+
| Innodb_dblwr_pages_written | 23196544 |
| Innodb_dblwr_writes        | 4639373  |
+----------------------------+----------+

通過InnoDB_dblwr_pages_written/InnoDB_dblwr_writes 就可以得到,通過指標也可基本看明白。

Percona中的double write改進

當然對於double write,在Percona中也在持續改進,在Percona 5.7版本中做了一個改進,你可以看到一個新的引數,innodb_parallel_doublewrite_path

| innodb_parallel_doublewrite_path | xb_doublewrite |

在系統層面,也會存在一個30的一個檔案對應。

-rw-r----- 1 mysql mysql 31457280 Mar 28 17:54 xb_doublewrite

也就是並行double write,關於這個特性的詳細描述和測試,可以參考。https://www.percona.com/blog/2016/05/09/percona-server-5-7-parallel-doublewrite/?utm_source=tuicool&utm_medium=referral

裡面提供了很多詳細測試的對比和分析。當然MariaDB,Facebook,Aurora也有一些自己的實現方式和考慮,這個限於精力,還沒有細細測試分析。感興趣的同學可以看一看。

參考連結:

https://yq.aliyun.com/articles/50627

http://blog.itpub.net/22664653/viewspace-1140915/