Dans l’optique de migrer l’instance de nextcloud 15 de mon petit auto-hébergement perso vers la version 16, afin de maximiser les chances de réussite, il est préférable de corriger tous les avertissements remontés dans le panel administrateur. Parmi ceux-ci, il peut y avoir le message suivant, demandant de changer le charset des tables avec mariadb.
MySQL est utilisée comme base de données mais ne supporte pas les caractères codés sur 4 octets. Pour pouvoir manipuler les caractères sur 4 octets (comme les émoticônes) sans problème dans les noms de fichiers ou les commentaires par exemple, il est recommandé d’activer le support 4 octets dans MySQL.
Il semble que ce message aurait du apparaître depuis longtemps, mais il se trouve que sur cette instance il n’est apparu que récemment.
Le message d’avertissement est accompagné d’un lien vers la page de documentation décrivant la manipulation à effectuer.
Dans le cas présent de l’utilisation de mariadb, après avoir vérifié que le moteur innodb était configuré pour utiliser un fichier par table, la commande suivante est exécutée dans le shell mariadb pour convertir le jeu de caractères et le paramètre de collation de la base de données (après avoir réalisé un snapshot de la machine virtuelle bien entendu, ou une sauvegarde la base de données):
MariaDB [(none)]> ALTER DATABASE owncloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Remarquons au passage qu’ici, la base de données s’appelle owncloud, car cette instance de nextcloud a été migrée depuis une instance owncloud (dont l’installation initiale a été faite sous owncloud 5 et mise à jour successivement par toutes les version intermédiaires jusqu’à la 10.0, puis migrée vers nextcloud 13) et que je n’ai jamais pris le temps de m’occuper de renommer la base de données.
On défini ensuite le paramètre « mysql.utf8mb4 » à « true » dans le fichier de configuration de nextcloud :
$ sudo -u www-data php occ config:system:set mysql.utf8mb4 --type boolean --value="true"
Enfin, on réalise la conversion de toutes les tables dans le nouveau jeu de caractères:
$ sudo -u www-data php occ maintenance:repair
Si tout se passe bien, l’opération est terminée. Dans le cas de cette mise à jour, ça ne s’est pas très bien passé et le message suivant est apparu sur fond rouge angoissant:
conversion du jeu de caractères
Nextcloud is in maintenance mode - no apps have been loaded
- Repair MySQL collation
- Change row format for oc_vcategory ...
- Change collation for oc_vcategory ...
In AbstractMySQLDriver.php line 115:
An exception occurred while executing 'ALTER TABLE `oc_vcategory` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;':
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
In PDOStatement.php line 107:
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
In PDOStatement.php line 105:
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
Arg.
Bon, d’après cette page du forum d’aide de nextcloud, il suffit d’activer les préfixes longs pour le moteur innodb. Ainsi soit-il.
# mysql -u root -p
MariaDB [(none)]> use owncloud;
MariaDB [owncloud]> set global innodb_large_prefix=on;
Et on relance la commande occ maintenance:repair pour convertir les tables, et c’est de nouveau le drame:
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes
Gniiiiiiiii.
La longueur maximum a bien été portée à 1000 octets, mais le script de maintenance butte sur une clé encore trop longue… A partir de là je n’ai pas trouvé d’informations décisives sur internet pour me sortir de l’impasse, il a donc fallu employer les grands moyens.
Dump de la base de données
# mysqldump --single-transaction -h localhost -u utilisateurbdd -p motdepasse owncloud > /root/owncloud.sql
Destruction de la vilaine table
# mysql -u root -p
MariaDB [(none)]> use owncloud;
MariaDB [owncloud]> DROP TABLE oc_vcategory;
Création de la table directement dans le bon charset
CREATE TABLE `oc_vcategory` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`uid` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`type` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`category` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `uid_index` (`uid`),
KEY `type_index` (`type`),
KEY `category_index` (`category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPRESSED;
Restauration des données de la table à partir de la sauvegarde
INSERT INTO `oc_vcategory` VALUES (1,'toto','event','Anniversaire'), (.....);
J’ai procédé de cette manière pour toutes les tables qui posaient des problèmes de conversion (il y avait aussi la table « oc_mimetypes ») et ainsi le script de conversion a pu venir à bout de la procédure.
o/