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

  1. 1. Remove 'recommended' from the MySQL heading on the DB requirements page.
  2. 2. Remove 'Percona' from the list and from code.

Remaining tasks

  1. Done. Doc page updated
  2. Decide if Percona should be removed.

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

Issue fork drupal-3478097

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

joseph.olstad created an issue. See original summary.

joseph.olstad’s picture

quietone’s picture

Title: MySQL should no longer be "Recommended" » [policy] MySQL should no longer be "Recommended"
Version: 11.0.x-dev » 11.x-dev
cmlara’s picture

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.

NOTE:
Mysql cli can treat 'localhost' as a local connection and use the socket. The below tests likely did not tested the TCP layer. Please review later posts for additional timing figures.

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.

joseph.olstad’s picture

Possibly socket test results above

With that said, our testing has focused on Azure. There's most likely cloud (pay-wall) tcp throttling software that is at play. I can only hypothesize that Microsoft Azure is not liking MariaDB because they maybe have difficulty monetizing/throttling tcp connections due to proxysql at play however this is speculation on my part.

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

joseph.olstad’s picture

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

Webserver host -> DB Server on another host

Better yet, try on Azure.

cmlara’s picture

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'

joseph.olstad’s picture

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 using 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 faster at about 13 seconds for a drush cr of the same distribution schema tested in both test cases.

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

joseph.olstad’s picture

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.

quietone’s picture

Issue summary: View changes
Status: Active » Reviewed & tested by the community

This was discussed amongst the release managers, @catch, @longwave and myself. We touched on the fact that MySQL is sort of stagnating, but also we have issues to bring MongoDB to core. It was a reminder that any 'recommendation' for a database server may change. But also, we can't drop mention of MySQL, it is still widely used and we test using it. We don't test with a Percona server, so that should be removed. It also come up that we understood the 'recommendation' to be about using a MySQL equivalent instead of PostGreSQL or SQLite, and not necessarily MySQL itself.

As for the text, we agreed that that heading could use an update. And we decided to reduce it to "MySQL, MariaDB, or equivalent".

longwave made their first commit to this issue’s fork.

longwave’s picture

Should we also drop mentions of Percona from the installer here? There are known Percona bugs (#3143562: Lock issues when clearing cache on Percona XtraDB cluster), and several other MySQL-compatible engines that we don't mention.

longwave’s picture

Status: Reviewed & tested by the community » Needs review
quietone’s picture

dcam made their first commit to this issue’s fork.

c-logemann’s picture

Even if MySQL would be faster or need less disc space I would try to avoid because I have a long history with problems that came with MySQL in several projects and were be "solved" by switching to MariaDB in the last 15 years. MariaDB even solved a problem with a special error on data structure on upgrading from MySQL 5.* to 8 in a customer project. For the related error code I only could find an entry in the WWW behind a paywall for commercial customers of oracle. We finally exported the database, copied it to an external MariaDB, exported it again and, then imported the database in MySQL 8 because MariaDB was able to just import and fix the error. And since we have fun with the new collations types which are only used by them. See for example: #3264580: MySQL collation complexities leads to backup incompatibilities

We also should warn users that both databases are not longer fully compatible in meaning of import/export is getting more and more complex especially with new JSON features.

dcam’s picture

While I was reviewing #3568123: Update INSTALL.txt for Drupal 12 last night I was reminded of this issue. Specifically, it's because I saw the Percona server version string in the INSTALL.txt file, which I wonder if anyone gave any thought toward when determining the D12 requirements. Would it be a good idea to wrap up this discussion before the Drupal 12 release?

quietone’s picture

Issue summary: View changes
dcam’s picture

Status: Needs review » Reviewed & tested by the community
Related issues: +#3568123: Update INSTALL.txt for Drupal 12

The MR looks good to me. I grepped core for "Percona" and didn't get any results. This will conflict with #3568123: Update INSTALL.txt for Drupal 12.

quietone’s picture

Title: [policy] MySQL should no longer be "Recommended" » MySQL no longer recommended and remove Percona

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new1.08 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Post-bot-rebellion rebase

longwave’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed 4a0524ee0a8 to main and b8243e09355 to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • longwave committed b8243e09 on 11.x
    task: #3478097 MySQL no longer recommended and remove Percona
    
    By:...

  • longwave committed 4a0524ee on main
    task: #3478097 MySQL no longer recommended and remove Percona
    
    By:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

heyyo’s picture

It looks like the performance difference seen between MariaDB and Mysql is caused BY TLS being enabled by default on MYSQL 8.
MariaDB 11.4+ enables TLS by default
http://mariadb.com/docs/server/security/encryption/data-in-transit-encry...

https://dev.mysql.com/doc/refman/8.4/en/using-encrypted-connections.html

andypost’s picture

@heyyo Great point, it explains TCP connection measurments but what about socket connection? Curios to see different results

heyyo’s picture

It seems local socket are already considered secured by MySQL, so TLS is not used.

https://dev.mysql.com/doc/refman/8.4/en/connection-options.html#option_g...

joseph.olstad’s picture

In this issue summary , examples are provided for tests of tcp/ip "127.0.0.1" and socket connection "localhost"

keep in mind, before looping 1000 times to null, make sure the test is functional once without redirecting to null (verify test sanity).