MySQL8.0.20からDoublewrite Bufferがいろいろ変わってるらしい
タイトル通りMySQL8.0.20からDoublewrite Buffer周りが結構変わっているようなので。
Doublewriter Bufferとは
復習がてらそもそもDoublewrite Bufferとは何なのかということから始めます。
Doublewrite Buffer(以降はダブルライトバッファと記述します)とはシステムテーブルスペースに含まれる領域の一つで、バッファープールの内容が書き込まれます。 バッファという名前はついていますが、メモリ上ではなくディスク上にあるため、mysqldを停止してもその内容は保存されます。
InnoDBはバッファープールのページをデータファイルに書き込む前に、ダブルライトバッファにフラッシュします。 もし、OSやmysqldそのものがページの書き込み中にクラッシュしてしまった場合、InnoDBはクラッシュリカバリ時にダブルライトバッファ中にあるページを見て、データファイルにその内容を書き込みます。
ダブルライトバッファへの書き込みはシーケンシャルに行われるので、データファイルへの書き込みの2倍の負荷にはなりません。 といっても、もちろんダブルライトバッファへの書き込みはオーバヘッドなのでZFSのようにファイルシステムのほうでアトミックな書き込みが保証されるのであれば ダブルライトバッファは無効にしたほうが良いです。
また大きなデータのインポートなどクラッシュしても元のデータが残るようなケースであれば、パフォーマンスを考慮してダブルライトバッファを予め無効にしてもいいでしょう。
そのような場合では、my.cnf
にskip_innodb_doublewrite
やinnodb_doublewrite=OFF
を記述します。
従来のダブルライトバッファはテーブルスペースに存在します。
これはinnodb_data_file_path
によって指定され、デフォルトではdatadir
下にibdata1
という名前で作成されます。
MySQL8.0.20からのDoublewrite Buffer
MySQL8.0.20からダブルライトバッファ関連のシステム変数が増えました。
具体的には下記の変数が増えています。
- innodb_doublewrite_dir
8.0.20からダブルライトバッファはシステムテーブルスペースから独立しており、単一のファイルとなっています。
この変数はダブルライトバッファファイルが作られるディレクトリを指定します。
デフォルトはdatadir
と同じです。
パフォーマンスを考慮するとここで指定するディレクトリは高速なストレージ上であることが望ましいです。
拡張子はdblwrとなっています。
[root@centos8-instance3:/var/lib/mysql]# ll *dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 00:48 '#ib_16384_0.dblwr' -rw-r-----. 1 mysql mysql 4456448 5月 3 00:48 '#ib_16384_1.dblwr' -rw-r-----. 1 mysql mysql 262144 5月 3 00:48 '#ib_16384_2.dblwr' -rw-r-----. 1 mysql mysql 4456448 5月 3 00:48 '#ib_16384_3.dblwr'
(この16384って何なんでしょう?)
- innodb_doublewrite_files
ダブルライトバッファファイルの数です。 デフォルトではinnodb_buffer_pool_instanceの2倍になるそうですが、僕が確認した限りそうではなかったです。 Yumリポジトリを使ってインストールしたのですが、innodb_buffer_pool_instanceが8でinnodb_doublewrite_filesは2となっていました。
2020/06/23追記 どうやらバグ?のようですね。
MySQL Bugs: #99935: innodb_doublewrite_files is not correct when innodb_buffer_pool_size > 1G
リファレンスの説明では各バッファープールインスタンスにつき2つ、フラッシュリスト用とLRUリスト用作られるとのことです。
フラッシュリスト用のダブルライトバッファファイルのデフォルトサイズはinnodb_page_size
* innodb_doublewrite_pages
バイトです。
LRUリスト用のダブルライトバッファファイルのデフォルトサイズは innodb_page_size
* (innodb_doublewrite_pages
+ (512 / innodb_buffer_pool_instance
))バイトです。
その性質上、最低でも2つのダブルライトバッファファイルが作られます。 また、最大数はinnodb_buffer_pool_instance * 2となり、ダブルライトバッファファイルの数はinnodb_buffer_pool_instanceで制御されます。
innodb_doublewrite_files
の値を奇数にしても問題なく起動できるようですが、大人しく偶数個にしておいたほうがいいかと思います。
[root@centos8-instance3:/var/lib/mysql]# ll *dblwr | sort -t "_" -k 3n -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_0.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_1.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_2.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_3.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_4.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_5.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_6.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_7.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_8.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_9.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_10.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_11.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_12.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_13.dblwr -rw-r-----. 1 mysql mysql 262144 5月 3 01:43 #ib_16384_14.dblwr -rw-r-----. 1 mysql mysql 1310720 5月 3 01:43 #ib_16384_15.dblwr
実際に見てみると#ib_16384_n.dblwr
というファイルが16個存在します。(innodb_buffer_pool_instance=8)
nが偶数となるファイルのサイズは262144なのでフラッシュリスト用、奇数となるファイルのサイズは1310720となっているのでLRUリスト用でしょうか。 フラッシュリスト用の方はデフォルトサイズの2倍になってますね🤔
- innodb_doublewrite_pages
スレッドごとの書き込みページ数の最大数です。
特に指定がない限りはinnodb_io_write_threads
と同等になります。
ほとんどの場合デフォルトでいいらしいようです。
- innodb_doublewrite_batch_size
バッチ書き込みのダブルライトのページ数を制御します。 デフォルトは0でこちらもほとんどの場合でデフォルトでいいらしいです。
リファレンスにはIntroducedに8.0.20とありますが、8.0.19(デバッグコンパイル)でも存在することを確認しています。
mysql80-root@localhost:[(none)] >SELECT version(); +--------------+ | version() | +--------------+ | 8.0.19-debug | +--------------+ 1 row in set (0.00 sec) mysql80-root@localhost:[(none)] >show variables like '%doublewrite%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | innodb_doublewrite | ON | | innodb_doublewrite_batch_size | 120 | +-------------------------------+-------+ 2 rows in set (0.02 sec)
ということでダブルライトバッファ周りが結構変わっているようでした。