MySQL should no longer be "Recommended"

Created on 1 October 2024, 7 months ago

Problem/Motivation

I recommend that we stop recommending MySQL as a back end service to host Drupal. We can still support MySQL without recommending MySQL.

There's a lot of confusion around MySQL as people using MariaDB will talk as if it is mysql. Cloud devops folks seem to have a false high opinion of mysql when in fact it they are ignorant of the actual history and current state of affairs.

MySQL with tcp especially and specifically when coupled with throttled IO cloud systems is performing pitifully compared to MariaDB.

Additional analysis comparing MariaDB to MySQL:

Measuring the /var/lib/mysql folders respectively from a fresh install and loading the same wxt based drupal dump file into both MySQL and MariaDB.

  1. Install db server, re-configure settings.php / settings.local.php accordingly
  2. load dump file for a real-world drupal wxt project
  3. rebuild drupal caches with drush cr
  4. turn off db service
  5. measure size of /var/lib/mysql folder(s)
  • MySQL folder contents size uncompressed approximately 5x more data compared to MariaDB uncompressed
  • measured as follows: du -h /var/lib/mysql/schemaname or du -h /var/lib/mysql (can't recall which one I compared, but both same comparison between MySQL/MariaDB)
  • MySQL data compressed: ~ 250mb
  • MariaDB data compressed: ~ 59 mb

Conclusion:

MySQL spreads it's filesystem out 5x larger than MariaDB with the exact same number of data rows and tables.
MariaDB performance is vastly superior in comparison. MariaDB is vastly more efficient.
MariaDB has built-in ProxySQL service which vastly improves TCP throughput and drastically reduces TCP latency . MySQL does NOT have this included by default and therefore suffers with very poor tcp performance.

Implications:

  • This means 5x more IO operations for the same data on MySQL compared to MariaDB which has a profound effect on performance.
  • Vastly improved tcp performance when using MariaDB in comparison to using MySQL.

installed MariaDB 10.6.15

ran tests

MARIADB 10.6.15 TCP (127.0.0.1) test

time (for i in {1..1000}; do mysql -h 127.0.0.1 -u username --password='password_password' database_name -e "select 1 from dual;" 2>&1; done)>/dev/null 
real	0m6.084s
user	0m3.403s
sys	0m2.546s

MARIADB 10.6.15 SOCKET test

time (for i in {1..1000}; do mysql -h localhost -u username --password='password_password' database_name -e "select 1 from dual;" 2>&1; done)>/dev/null 
real  0m5.946s
user 0m3.224s
sys   0m2.608s

then on the same server -
purged MariaDB then:

MySQL 8 installed

MySQL v8 TCP (127.0.0.1) test

time (for i in {1..1000}; do mysql -h 127.0.0.1 -u username --password='password_password' database_name -e "select 1 from dual;" 2>&1; done)>/dev/null 
real	0m15.260s
user	0m9.498s
sys	0m4.024s

MySQL v8 SOCKET test

time (for i in {1..1000}; do mysql -h localhost -u username --password='password_password' database_name -e "select 1 from dual;" 2>&1; done)>/dev/null
real  0m6.649s
user 0m3.492s
sys   0m2.909s

Conclusion: MariaDB 10.6.15 handles TCP much more efficiently than MySQL v8 given a default configuration with only one option set
The only option set was:
max_allowed_packets=64M

Same option set for both installations and test runs.

MySQL taking 15.260 seconds to complete the TCP test
MariaDB taking 6.084 seconds to complete the TCP test. <-- MariaDB 10.6.15 wins by a huge margin.

Steps to reproduce

See issue summary

Proposed resolution

Please update the database server requirements page.
https://www.drupal.org/docs/getting-started/system-requirements/database... β†’

Remaining tasks

Please remove mention of MySQL on the database server requirements page, or make it obvious that while we do support MySQL, it is NOT recommended.
https://www.drupal.org/docs/getting-started/system-requirements/database... β†’

User interface changes

Vastly improved performance

API changes

N/A , continue to support MySQL however do NOT recommend it.

Data model changes

None

Release notes snippet

TBD

🌱 Plan
Status

Active

Version

11.0 πŸ”₯

Component

documentation

Created by

πŸ‡¨πŸ‡¦Canada joseph.olstad

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @joseph.olstad
  • πŸ‡³πŸ‡ΏNew Zealand quietone
  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    Did a couple quick tests, grabbed what was on the top of docker hub.

    Modified the test sample a bit, removed the selecting from the table which might invoke data access layers, disk caches, etc and went for a simple in memory "select 1" which puts us through some of the most performance impacting portion of the test (connection establishment) and should exercise most of the TCP stack of both implementations.

    Test performed on a non-performance tuned laptop.

    MariaDB 11.5.6
    Note: this required installing the mysql-client package in the docker image as it is not included by default.

    
    root@c3c4e37d23f4:/# time (for i in {1..1000}; do mysql -h localhost -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m7.469s
    user	0m3.735s
    sys	0m3.371s
    
    
    root@c3c4e37d23f4:/# time (for i in {1..1000}; do mysql -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m7.115s
    user	0m3.579s
    sys	0m3.201s
    
    

    MYSQL 8.0.39:

    root@639faa18ba64:/# time (for i in {1..1000}; do mysql -h localhost -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m7.981s
    user	0m4.312s
    sys	0m3.289s
    
    root@639faa18ba64:/# time (for i in {1..1000}; do mysql -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m7.839s
    user	0m4.219s
    sys	0m3.234s

    Both tests used stock configs as included in the dockerhub images. Both images do have skip_name_resolve.

    Given no configs were given in the examples I would wonder if one of the deployments did not have skip_name_resolve. Over 1000 connections that could easily increase the runtime by a factor of 3x.

    I did not load a full database into the system however I noted on SLACK using 5x the disk space does not mean 5.x the IO. It could be provisioning space in advance, the engine might read larger block segments at a time, etc. There are a LOT of factors that are not documented in this post.

    There are a lot of factors that go into database performance. I'm not saying Mysql or Mariadb have the same performance, only that as far as databases are concerned, deployment and configuration is generally up to a DBA and a sysadmin.

    I would however expect if the performance of MariaDB with TCP is actually always 300% better than Mysql that it should be easiy to cite reference papers that backup the assertion with detailed documentation of the deployments to allow reproducing the results.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    I see socket tests above , I don't see a TCP ip in the select statement mentioned above.

    With that said, our testing has focused on Azure. There's most likely cloud (pay-wall) tcp throttling software that is at play.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    To fully see the TCP performance gap between MariaDBs proxysql and mysql, suggest to consider:

    Webserver host -> DB Server on another host

    Better yet, try on Azure.

  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    Possibly socket test results above

    I copied your commands, however I forgot that the mysql cli client gets fancy with "localhost" and can bypass the TCP stack to use the socket. Re-running the tests with 127.0.0.1 which does not bypass the TCP stack.

    Any chance you may have made the same error in testing with mariadb?

    Mysql:

    root@7d4aba32d039:/# time (for i in {1..1000}; do mysql -h 127.0.0.1 -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m13.991s
    user	0m7.940s
    sys	0m3.851s
    
    root@7d4aba32d039:/# time (for i in {1..1000}; do mysql -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m8.588s
    user	0m4.651s
    sys	0m3.376s
    

    Mariadb:
    NOTE: The results on this are so outlandish I have trouble believing them, however I ran them multiple times with similar results. I consider this result to be invalid however I'm posting them in the spirit of not withholding data and showing that without tuning the setup there can be one setting somewhere that can throw off an entire test set. I have not dug in to evaluate what caused this massive increase compared to Mysql.

    root@9fda3699b273:/# time (for i in {1..1000}; do mysql -h 127.0.0.1 -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m55.082s
    user	0m43.279s
    sys	0m4.949s
    
    
    root@9fda3699b273:/# time (for i in {1..1000}; do mysql -u root --password='test' test -e "select 1;" 2>&1; done)>/dev/null;
    
    real	0m7.524s
    user	0m3.737s
    sys	0m3.460s
    

    Even if I assume that worst case Mariadb sees zero decrease using the TCP stack

    MariaDB comes through much faster with tcp binding on 127.0.0.1 or a mariadb endpoint on another host compared with MySQL.

    I did not see that included in your tests above. At that point your now including a lot more factors. Performance tuning becomes even more important. This is the point that you need to involve your DBA and your Sysadmin to make these configuration changes. I do expect remote connections to be more variable, and to be more susceptible to even minor issues. Again though if your reaching this point you likely are involving the appropriate stakeholders to properly evaluate your database engine choice.

    Better yet, try on Azure.

    I would suggest we focus on local testing before involving third parties that have even more significant variables related to them that we can not control

    How about GitLab CI results? They exercise a large amount of the code base: I grabbed a pipeline earlier today and checked the Functional PHPUnit job (has 7 sub jobs for both). I did not normalize for container setup time or anything else so there is possibly some variance in this data.

    MySQL did take about ~35 minutes compared to Mariadb taking ~25. 1.4x the runtime, but not 3x. the runtime. Those tests use a 'network connection' across multiple 'pods'. This does involve full tcp stacks of multiple systems, however it does avoid the random jitter and slowness of real wirespeed.

    MariaDBs proxysq

    Can you link me to the manual page on this? This sounds like were not longer testing the database itself and now involving a cluster setup, one that perhaps might be included with the product but not enabled by default. At that point are we also testing the same thing? If mysqld doesn't include one in the standard package but allows you to provide your own that can still be expected to be part of 'tuning your database server'

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Interesting results from your tests!

    Try reducing the count from 1000 to 1 and remove the redirect to null (>/dev/null) to make sure that the test is returning the expected result.

    I didn't mention this but to ensure the test is running correctly before scaling it up to 1000 and remove the dev null redirect.

    With that said, a simple test of drush cr showed well above 30 seconds for a mysql Server B setup within the azure cloud
    Whereas the cheapest mariadb on server B was much better.

    Our tcp results may be skewed due to packet filtering in black blox networks we're dealing with.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    also, I made sure that all the configs were default between tests. the -client software for mariadb used when connecting to mariadb and the mysql client software used to connect to mysql , all with default configurations. I believe even max_allowed_packet is fine for Drupal now with the latest defaults but if there was a setting changed, this would be the only setting.

Production build 0.71.5 2024