The new MySQL-8.0.20 release is coming with re-designed InnoDB Double Write Buffer (DBLWR), and, indeed, it's one huge historical PITA less.. -- why it was so painful and cost us much blood in the past, I could not better explain than already done it in the following article yet from 2018 about MySQL on IO-bound workloads.. The story is not complete, as it's missing the 2019's chapter (will tell it later, np) -- but if you'll (re)read the mentioned above article first, you'll better understand the next ;-))

But at least the current post is only about good news now -- the new DBLWR and how it helps to solve historical MySQL performance problems ! -- and as one picture is better than million words, I'll try to save 3M words here (as there are 3 pictures in this article ;-))

Well, I'll also skip all new design details (I think Sunny will better explain them all himself "from the first hands") -- I'll only mention the following :

  • the DBLWR is no more part of "system tablespace", and can be placed anywhere you like (so, if you have a possibility to use a different storage for DBLWR files, you can totally get a rid of DBLWR impact on your main storage) -- but by default, DBLWR is stored in the same directory as your DATA
  • you can configure how many DBLWR files you want to use
  • and also how many pages per DBLWR files to have (which is also directly related to final DBLWR file size)

For more details about config options you can check MySQL 8.0 doc about DBLWR explaining this all in details.

Enough words, let's go to the test results..

Test Workload Scenario

  • a simple Sysbench OLTP_RW test is used here
  • 8 tables, each of 50M rows (~100GB data)
  • InnoDB Buffer Pool (BP) is sized first to :
  • 128GB (in-memory workload)
  • then 64GB (partially IO-bound)
  • then 32GB (heavy IO-bound)
  • load level is progressively growing from 1, 2, 4 .. 1024 concurrent users
  • same test is executed on MySQL-8.0.19, then MySQL-8.0.20

HW/SW Platform / Config

  • Server : 48cores-HT Intel(R) Xeon(R) Platinum 8268 CPU @ 2.90GHz, 192GB RAM
  • Storage : Intel Optane NVMe, XFS filesystem
  • OS : OL7.6, kernel-4.14.35-1902.301.1.el7uek.x86_64
  • MySQL config : full my.conf used during the testing is attached at the end
  • Note : DBLWR files are configured by default and stored in the same directory as DATA and REDO (also by default as well)

And few words about the following graphs.. -- they are not really "user friendly" (as marketing guys would love ;-)) but they are simply reflecting real TPS levels obtained over growing load levels. And TPS is growing as the load level is growing (1 user first, then 2, then 4, and so on, from the left to right) -- well, feel free to ping me if you're finding something unclear, etc. ;-))

Using 128GB Buffer Pool

  • as expected, DBLWR is not impacting on in-memory workloads as long as you're able to setup your MySQL instance to hide doubled latency of page O write..
  • (this can be achieved by using faster storage or bigger REDO size, etc.)
  • page flushing is going in background, and as soon it'll go fast enough to follow your REDO writes, you're safe ;-))

Using 64GB Buffer Pool

  • however, once your workload becomes IO-bound, the game is changing..
  • any delay on page writes will delay your IO reads !
  • and the old DBLWR design was not made for high concurrency..
  • (but, as you can see, up to 64 users load level it was still ok ;-))

Using 32GB Buffer Pool

  • with 32GB BP only 1/3 part of data can be kept "cached"
  • and with "uniform" access pattern we're heavy IO-bound here..
  • so, overall impact on TPS is yet more bigger
  • but DBLWR impact is very similar to previous test result -- able to resist up to 64 users, then totally loosing performance..

SUMMARY

  • so far, one historical huge PITA is less.. -- KUDOS Sunny !! ;-))
  • but mind that with MySQL 8.0 we're in "continuous release" model ;-))
  • which simply means -- yet more fun stuff is coming ;-))
  • so, stay tuned.. ;-))

Thank you for using MySQL !

Rgds, -Dimitri

APPENDIX

my.conf :

[mysqld] # general  max_connections=4000  back_log=4000  ssl=0  table_open_cache=8000  table_open_cache_instances=16  default_authentication_plugin=mysql_native_password  default_password_lifetime=0  max_prepared_stmt_count=512000  skip_log_bin=1  character_set_server=latin1  collation_server=latin1_swedish_ci  skip-character-set-client-handshake  transaction_isolation=REPEATABLE-READ # files  innodb_file_per_table  innodb_log_file_size=1024M  innodb_log_files_in_group=16  innodb_open_files=4000 # buffers  innodb_buffer_pool_size=128000M / 64000M / 32000M  innodb_buffer_pool_instances=24  innodb_log_buffer_size=64M # tune  innodb_doublewrite=1  innodb_thread_concurrency=0  innodb_flush_log_at_trx_commit=1  innodb_max_dirty_pages_pct=90  innodb_max_dirty_pages_pct_lwm=10  join_buffer_size=32K  sort_buffer_size=32K  innodb_use_native_aio=1  innodb_stats_persistent=1  innodb_spin_wait_delay=6  innodb_max_purge_lag_delay=300000  innodb_max_purge_lag=0  innodb_flush_method=O_DIRECT  innodb_checksum_algorithm=crc32  innodb_io_capacity=20000  innodb_io_capacity_max=40000  innodb_lru_scan_depth=1000  innodb_change_buffering=none  innodb_read_only=0  innodb_page_cleaners=24  innodb_undo_log_truncate=off # perf special  innodb_adaptive_flushing=1  innodb_flush_neighbors=0  innodb_read_io_threads=16  innodb_write_io_threads=4  innodb_purge_threads=4  innodb_adaptive_hash_index=0 # monitoring  innodb_monitor_enable='%'  performance_schema=ON # etc.  loose_log_error_verbosity=3  secure_file_priv=  core_file  innodb_buffer_pool_in_core_file=off