New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use utf8mb4 character set if possible #15618
Conversation
99db12f
to
c34c12e
Compare
9917e48
to
444236b
Compare
0d6f3cc
to
82aab9d
Compare
@tsteur @diosmosis could you maybe have a first look at the PR? What still needs to be clarified:
|
|
||
if (empty($result) || $result['Value'] !== 'ON') { | ||
return 'utf8'; // innodb_file_per_table is required for utf8mb4 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we cache the result of this function? And haven't been following this issue, but do we need to do the innodb_file_per_table
check if character_set_database
is set to utf8mb4
, or can we just assume it will work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe we can set Config::getInstance()->database['charset']
if it's not set to the default...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I see this is already done during installation/update, so maybe that's enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was wondering the same if we need to check for SHOW VARIABLES LIKE 'character_set_database'
after innodb_file_per_table
?
It would have to be a major update though, correct? Since it would update a bunch of columns (not sure if those affect log tables). If it's too intensive an operation, maybe it could be a command that users can run when they're ready.
Would it help to check the database charset config, and check if a table has the right charset/column length to check if the update was run? This would still be a problem if some tables have different charsets, but that sounds like a real edge case.
Only one that looks like it could be an issue is the option_name change. There might be some dynamically created one that somehow gets too long. Maybe we can report when the option name is too long somehow? |
Just for reference, this is how Nextcloud handled the upgrade: (They did it in a console command) https://docs.nextcloud.com/server/18/admin_manual/configuration_database/mysql_4byte_support.html |
Sure. Providing a command to do the migration makes it possible for those people that have shell access. But those using a shared hoster without shell access, wouldn't have the possibility to upgrade later. But maybe we could force the same update in Matomo 5 (for those that haven't switched till then). So using utf8mb4 is kind of optional for Matomo 4, but a requirement for Matomo 5. Would that be reasonably @mattab @tsteur |
The mechanism to make the change could also be in the UI if needed, right? Doesn't have to be a command. |
@diosmosis I've updated the PR. So here a summary of the current behavior. Maybe @tsteur or @mattab have some thoughts/comments on that as well:
|
just checking, we wouldn't force the conversion if it's not available though, to prevent errors/breaking instance? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sgiehl there's still a test failing in https://travis-ci.org/github/matomo-org/matomo/jobs/686048413#L668
Would expect that only tables starting with archive_
are returned.
Otherwise looked good. The only thing I would maybe do is when executing the command instead of showing the table names
Maybe we could show all the SQL queries we will be executing in case someone wants to execute these manually? And then show at the end a command ./console config:set --section=database --key=charset --value=utf8mb4
. I reckon some bigger installs like us might prefer to execute these queries manually as it can take a long time. Eg you want to update one log table over night, then another table another night when there is low traffic etc. (as you have to pause tracking during this time likely). There could also be a question whether they want the SQL plus config set instructions to be printed in order to execute it manually or whether they want it to be executed automatically?
This also makes me think if there should be an option to automatically disable tracking while the log tables are being migrated. Not sure but this might be even a good idea to do by default? If someone has low traffic, then tracking be down only for short time anyway. If someone has a a big DB, then they might get in trouble when keeping tracking enabled as I'd expect the inserts to be not processed but haven't tested this. It seems converting charset has no online DDL supporthttps://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html#online-ddl-table-operations so would expect it might be best to disable tracking during the migration of log tables. fyi @mattab
@tsteur applied some feedback and adjusted the command so it is able to disable tracking and only show all required commands... |
|
||
$isWritable = Piwik::hasUserSuperUserAccess() && CoreAdminController::isGeneralSettingsAdminEnabled(); | ||
$dbSettings = new Settings(); | ||
if ($dbSettings->getUsedCharset() !== 'utf8mb4' && DbHelper::getDefaultCharset() === 'utf8mb4') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just fyi was worried this might issue DB requests during tracking but double checked looks like these system settings aren't used during tracking 👍 Might be good though to change the if
to if ($isWritable && $dbSettings->getUsedCharset() ...)
? This way eg on cloud we avoid these queries there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be last thing. feel free to merge if/once tests pass
4a689bb
to
27d4c13
Compare
@sgiehl not sure... BTW another option could be when posting the event to try Piwik::postEvent('Db.getTablesInstalled', [&$allMyTables], false, (Manager::getAllPluginsNames()); // and if this doesn't work could try the array_keys($loadedPlugins) |
@tsteur actually it should load the plugins that were loaded before. But I can try to revert that to btw. Passing the plugins to the postEvent won't work, as the method only checks loaded plugins. |
@tsteur using |
fixes #9785