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.
- Install db server, re-configure settings.php / settings.local.php accordingly
- load dump file for a real-world drupal wxt project
- rebuild drupal caches with
drush cr - turn off db service
- 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/schemanameordu -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. Remove 'recommended' from the MySQL heading on the DB requirements page.
- 2. Remove 'Percona' from the list and from code.
Remaining tasks
- Done. Doc page updated
- 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
| Comment | File | Size | Author |
|---|
Issue fork drupal-3478097
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:
- 3478097-policy-mysql-should
changes, plain diff MR !12725
Comments
Comment #2
joseph.olstadComment #3
quietone commentedComment #4
cmlaraDid 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.
MYSQL 8.0.39:
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.
Comment #5
joseph.olstadPossibly 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.
Comment #6
joseph.olstadTo 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.
Comment #7
cmlaraI 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:
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.
Even if I assume that worst case Mariadb sees zero decrease using the TCP stack
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.
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.
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'
Comment #8
joseph.olstadInteresting 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.
Comment #9
joseph.olstadalso, 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.
Comment #10
quietone commentedThis 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".
Comment #12
longwaveShould 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.
Comment #14
longwaveComment #15
quietone commentedFor reference Percona was added in 2013 in #2062399: Add Percona Server to list of supported MySQL alternative databases.
Comment #17
c-logemannEven 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.
Comment #18
dcam commentedWhile 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.txtfile, 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?Comment #19
quietone commentedComment #20
dcam commentedThe 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.
Comment #21
quietone commentedComment #23
needs-review-queue-bot commentedThe 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.
Comment #24
dcam commentedPost-bot-rebellion rebase
Comment #25
longwaveCommitted and pushed 4a0524ee0a8 to main and b8243e09355 to 11.x. Thanks!
Comment #31
heyyo commentedIt 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
Comment #32
andypost@heyyo Great point, it explains TCP connection measurments but what about socket connection? Curios to see different results
Comment #33
heyyo commentedIt 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...
Comment #34
joseph.olstadIn 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).