Problem/Motivation
It is not possible to configure MySQL to use a (different) row format. In some cases, you might need to use a different row format, for instance when creating custom indexes on entity tables having multiple large text base fields (by default MySQL/MariaDB have a key prefix length limit 767 bytes for InnoDB which is only 191 utf8mb4 characters*)
Another motivation is that the disk usage overhead by having many databases/tables can be reduced significantly with row format compressed.
Steps to reproduce
There is no current way to achieve this.
Proposed resolution
Make it possible to configure MySQL's ROW_FORMAT in the database settings similar to how it is possible to configure collation:
$databases['default']['default'] = [
'database' => 'databasename',
'username' => 'sqlusername',
'password' => 'sqlpassword',
'host' => 'localhost',
'port' => '3306',
'driver' => 'mysql',
'prefix' => '',
'collation' => 'utf8mb4_general_ci',
'row_format' => 'compressed',
];
Remaining tasks
Decide if tests are needed, @daffie asked for tests in #57 followed by a reply explaining why tests are not needed.
In #59, @andypost points out that new images may be needed.
User interface changes
None.
API changes
Adds the row_format key to the database configuration in settings.php.
Data model changes
None.
Release notes snippet
MySQL's row format is now configurable in the database settings
*See:
| Comment | File | Size | Author |
|---|
Issue fork drupal-2857359
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
Comment #2
boobaaCould you please describe what the problem really is and how to easily trigger it?
Comment #3
tamasd commentedComment #7
arnested commentedI think Dynamic is already the default row format for InnoDB: https://dev.mysql.com/doc/refman/8.0/en/innodb-row-format-specification....
I don't know when it was introduced as default though so there might be a need for specifying it explicitly with older MySQLs.
Hard coding
dynamicdoesn't seem very flexible though.As an example I have some sites where we need to cut down on disk usage and therefor use row format
compressed(depends on file format Barracuda).I suggest making it an option in the database settings similar to collation:
I have made a patch doing that.
The patch lacks a test case. I'm still researching how to test this (there is no similar test for collation unfortunately) -- ideas and pointers would be welcome.
Comment #8
arnested commentedI have looked into writing a test for this and I can't figure out how to do that. I haven't found a way to manipulate database settings for a test (it is possible to I haven't looked hard enough). The feature is very similar to the collation feature and that feature isn't covered by a test either.
Comment #9
arnested commentedUpdated patch where the new option is documented in
default.settings.php.Comment #12
jcnventuraFor those using composer-patches, patch in #7 is the one to include...
Comment #13
arnested commentedRe-rolled patch to 8.8.x.
Comment #15
mvcWe're doing the equivalent in D7 because our DBAs insisted on using the compressed row format. Our db servers are I/O bound (as they usually are) so the smaller files are well worth the extra processing time. The patch looks about the same but I can backport it once this is accepted in D8 (or D9?). For now I've submitted a patch to utf8mb4-convert to handle this case: #3088343: Multiple patches: include additional tables, use compressed row format, use utf8mb4_bin only where needed
Comment #20
cosolom commentedRerolled for D9.4
Comment #22
murilohp commentedJust fixing the fail test and add some more documentation here, it would be nice to have other thoughts regarding the tests and the solution.
Comment #24
jcnventuraUploading a version of #22 that can be applied via composer patches.
At least until #3075954: Remove duplicate scaffold files is not applied. If that happens, then this is the patch to use.
Comment #25
jcnventuraComment #27
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #28
arnested commentedRerolled for 10.1.x and improved comments a bit.
Comment #29
arnested commentedComment #31
arnested commentedThe one error is because of the change to
default.settings.-phpwhich makes CI fail on comparing it to duplicateddefault.settings.-phpin Scaffold. See #3075954.Comment #32
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
This needs an issue summary update as we are adding something to the database layer. What's the proposed solution to tackle this issue? Remaining tasks?
This will need test coverage as well
Once everything is agreed a change record will be needed to announce this change.
Comment #36
arnested commentedComment #37
arnested commentedUpdated issue summary.
Fixed failing test case.
Comment #38
arnested commentedComment #39
smustgrave commentedPosted in #testing for testing and @FeyP made the suggestion
Think that's a good start for the tests.
Comment #40
arnested commentedThank you for the hints, @smustgrave and @FeyP!
I managed to create a working test case for this now. I couldn't have done it without you!
Comment #41
smustgrave commentedRan the test without the fix and the first fails
Expected :'Compact'
Actual :'Dynamic'
Which is expected.
Good job on the test!
Comment #42
daffie commentedI do not see, why we should do this issue. In the issue summary is the reason given that we should do it, because it will reduce disk use. As disk are super cheap, this is not a good enough reason to do this issue. Cahnging the status to will not fix. If somebody has a better reason for why we should do this issue, than please add it and change to status to needs work.
Comment #43
jcnventuraI remember the reason why I started having this problem was that the index key prefix length limit is 767 bytes for InnoDB tables using the default (COMPACT) row format. This 767 bytes quickly reduces to 191 UTF-8 characters. On the site where this occurred, I use views to quickly display several custom entities that have large text fields, and needed to create custom keys to speed up those queries, at the expense of a larger index file.
People running into similar problems that require the ability to change the row format should not have their hands tied by Drupal's inability to pass this parameter to the MySQL connector.
See:
* MySQL: https://dev.mysql.com/doc/refman/8.4/en/innodb-limits.html
* MariaDB: https://mariadb.com/kb/en/innodb-dynamic-row-format/
Comment #44
jcnventuraSetting to "Needs work" as per the MR comments in #42.
Comment #45
quietone commentedThis needs to be committed to 11.x (which is main) first and then applied to branches.
Comment #46
jcnventuraComment #50
arnested commentedI have added an 11.x merge request for this. All merge request comments have been resolved.
I was the one citing disk space as a reasoning in the first place. I can elaborate a bit on why this was important for us.
We run a single server with currently 450 small, low traffic sites. The overhead of the database tables, even without any real content, was huge before we added row format compressed.
6 years ago, we started out with 401 sites. After doing site install of 300~ sites, we had filled up the 100 GiB disk. After shifting to row format compressed we had plenty of available disk space.
The change is small, it only affects the MySQL driver, and the change is in line with similar features for the MySQL driver, e.g. the "collate" option.
Comment #52
smustgrave commentedWith a new settings variable going to need a change record for what it does
If possible examples are also useful.
Thanks for keeping this one going.
Comment #53
arnested commented(Attempt at) Change Record added.
Comment #54
smustgrave commentedCR is straight forward.
Ran test-only feature here https://git.drupalcode.org/issue/drupal-2857359/-/jobs/2264362 and shows multiple failures so coverage is good.
Believe this one is good. Would suggest maybe a 11.1 highlight?
Comment #55
quietone commentedLet's get a subsystem maintainer review here, since they asked a question in #42. I left a suggestion in the MR as well, so setting to needs work for that doc change.
And a title change to indicate that this is MySQL only would help.
Comment #56
quietone commentedI made the doc change and changed the title. Leaving at RTBC
Comment #57
daffie commentedIt is not clear to me which row format options Drupal is going to support. Are we are going to support any other one than the default one. Could we update the CR with this information. Including which is the default row format option? With these kind of changes the CR becomes very important to me. There should be information on which row format options there are and what they do. If you are a site owner, it should be clear what the options are, what they do and when to use them. Now the CR is missing that information.
It would be great if we could add an installer test to see if we can install Drupal with another row format option other then the default one.
The PR should pass the testbot for MySQL and MariaDB.
Comment #58
jcnventuraThe change request now contains information on the different row formats and which is the default one.
I don't think that this should really need a test to check if Drupal works with other row formats. This is simply passed on to the database server when creating a table, and we would only be testing database engine functionality and not Drupal. It is the responsibility of the database engine to support the different row formats and make that transparent when that table is used.
Comment #59
andypostProbably CI images needs update #3468905: Update default system encoding setting for Mysql images before merging it as all Mysql 8.0+ images complain in logs about default encoding
Comment #60
quietone commentedUpdated the remaining tasks regarding the question of tests and about testing images. All from the last 4 comments.
Comment #61
alexpottI think this is more complex than we have here. If we just set it in Drupal settings then if someone runs optimize on the db server it will change back again... from the MySQL docs:
In my opinion, somethings are just best left as things to do on the database and not for Drupal to do.
But the change here is going to add row format to every create table so now things that used to work to change for all tables is no longer going to work. You'll have to change the global and then set the row format on every table.
I'd be tempted to make this a documentation task and to provide good docs pointing MySQL and MariaDB docs on the subject and to detail tables where you might want to change to COMPACT if available. But also given that the default is DYNAMIC on the versions of DB drivers supported by Drupal 11 I'm not sure that this change is that necessary anymore.
Comment #62
arnested commentedNot really.
Setting the row format in Drupal doesn't alter the database's default row format. It sets the configured row format on each of the tables Drupal creates.
Running
mysqloptimizedoesn't change it back. The table keeps its row format.Comment #63
jcnventuraThis is the problem. It can't be a documentation task.. Drupal has no way to support this. None. You can't document what Drupal blocks you from doing. What we want here is precisely the option to be able to pass this so that it can be documented.
Comment #64
alexpottDrupal doesn't stop you from changing your databases default row format. And setting it on every table makes it harder to manage on the database end.
Comment #65
alexpottRe documenting this... we could display the default row format using system_requirements_runtime() and link to good documentation about what the choices are and why you might make them.
Comment #66
alexpottI see... you can't set compressed as the default format...
So some general thoughts:
Comment #67
jcnventura@alexpott, the same reasoning applies to the "collation" setting of the current database configuration. No one should be changing it in runtime but if you do, it only applies to newly created tables. At least that is my understanding that if you set it to "utf8mb4_general_ci", you won't start to have problems with tables created with other collations. It's just that all newly created tables will store text as UTF-8.
Comment #68
alexpott@jcnventura but the point is you are not likely to want to set all tables to COMPRESSED
Also \Drupal\Core\Command\DbDumpCommand::getTableSchema() needs updating to support this I guess. And we need to work out how. I think mysqldump will only add ROW_FORMAT to create table when it has been explicitly set for a table.
Comment #69
alexpottAlso I think databases have moved on from COMPRESSED row format - see https://mariadb.com/kb/en/innodb-page-compression/#comparison-with-the-c... and https://dev.mysql.com/doc/refman/8.4/en/innodb-page-compression.html#:~:....
As per the first link:
Perhaps we should look to implement this for all revision tables...
Comment #70
jcnventuraI do remember when I started this that my problem was that Drupal created all tables as COMPACT, and I needed them to be DYNAMIC. I believe this was because I was using MariaDB 10.1 before this was changed to DYNAMIC in MariaDB 10.2.2. This is according to my Lando configuration at the time (DDEV was still v0.17 back then...).
I'm now using MariaDB 10.11, so I should probably remove this patch from my composer.json, and stop trying to chase this cart.
Even though it is no longer useful for my original purposes, I think the fact remains that this is a parameter that can be nice to have in the Drupal configuration to provide access to this setting of MySQL/MariaDB. And yes, one might argue if it makes sense to be able to do this. I'm not suggesting that anyone should change the defaults.. I'm only advocating for having the option to provide this setting.
However, maybe the best would be to have a generic way to provide ANY of the options supported by MySQL (https://dev.mysql.com/doc/refman/8.4/en/create-table.html#create-table-o...), and then have a way to expand the key/values provided in that setting into key=value parameters added to the create table command.
Comment #71
andypost@jcnventura it sounds like option for contrib module a-la Schema
Comment #72
andyf commentedRe #69
I was curious about InnoDB transparent page compression and read up a little, and noted a couple of points that might help inform whether to use it by default. From Percona articles around 2018: