Projet

Général

Profil

Anomalie #23635

Version 1.0+2-45 plante au reconf : la taille de l'index sur la table url est trop longue

Ajouté par Renaud Dussol il y a environ 6 ans. Mis à jour il y a plus de 5 ans.

Statut:
Fermé
Priorité:
Normal
Assigné à:
Version cible:
Début:
16/04/2018
Echéance:
% réalisé:

100%

Distribution:

Description

Sur run-parts: executing /usr/share/eole/postservice/30_dispatcher reconfigure

PHP Fatal error: Uncaught [42000] - SQLSTATE42000: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
trace: #0 /var/www/html/edispatcher/include/rb.php(651): RedBeanPHP\Driver\RPDO->runQuery('ALTER TABLE `u...', Array)
#1 /var/www/html/edispatcher/include/rb.php(2646): RedBeanPHP\Driver\RPDO->Execute('ALTER TABLE `u...', Array)
#2 /var/www/html/edispatcher/include/rb.php(8021): RedBeanPHP\Adapter\DBAdapter->exec('ALTER TABLE `u...', Array)
#3 /var/www/html/edispatcher/include/rb.php(8599): RedBeanPHP\Facade::query('exec', 'ALTER TABLE `u...', Array)
#4 /var/www/html/edispatcher/utils/createStructure.php(178): RedBeanPHP\Facade::exec('ALTER TABLE `u...')

Si on regarde /var/www/html/edispatcher/utils/createStructure.php :

178 \R::exec("ALTER TABLE `url` CHANGE `url` `url` VARCHAR;"); // fixes #22746

Apparemment en innoDB, la taille des index est limitée à 767 bytes...

Révisions associées

Révision 290e7a50 (diff)
Ajouté par Christophe LEON il y a presque 6 ans

fixes #24325 , ref #23635 , Mettre en place un flag pour le numéro de version de la base afin de gérer la migration de url => md5(url)

Historique

#1 Mis à jour par Renaud Dussol il y a environ 6 ans

Apparemment la taille max que l'on peut mettre est 191
Pourquoi ? Mystère pour l'instant...

#2 Mis à jour par Nicolas Penot il y a environ 6 ans

Pour ma part, j'avais remplacé la valeur 150 par 255 et ça fonctionne.

Voir ici : https://dev-eole.ac-dijon.fr/issues/22746#note-3

\R::exec("ALTER TABLE `url` CHANGE `url` `url` VARCHAR;");

#3 Mis à jour par Nicolas Penot il y a environ 6 ans

Il m'avait viré le 255 dans varchar ()...
J'avais écris :

\R::exec("ALTER TABLE  `url` CHANGE  `url`  `url` VARCHAR( 255 );");

#4 Mis à jour par Renaud Dussol il y a environ 6 ans

Réponse : en utf8mb4 (ce qui est le cas de notre table), chaque caractère occupe 4 bytes
En InnoDB la max size d'un préfixe est 767
Donc le max est 191 (192 x 4 = 768) si on reste en utf8mb4
Si on passe en utf8 simple on peut aller jusqu'à 255

Autres options : utiliser MyISAM (limite à 1000 bytes donc 250 cars en utf8mb4 et 333 en utf8)
Ou passer en latin1 mais bon...

#5 Mis à jour par Renaud Dussol il y a environ 6 ans

Le passage en MyISAM sera impossible vu qu'on a des clés étrangères et je pense qu'on utilise des transactions avec rb

Donc le max sera de 255 à moins de passer la colonne en latin1... Je peux tester

#6 Mis à jour par Renaud Dussol il y a environ 6 ans

Sur suggestion de C. Léon :

- créer un nouveau champ dans la table url nommé "md5url" CHAR (32) ascii_general_ci
- UPDATE URL set md5url = md5(url)
- virer l'index sur url
- mettre l'index sur md5url

TODO :
- modifier le createstructure
- côté appli :
- Lors de l'insert ajouter le md5url
- find sur le md5 au lieu de l'url

#7 Mis à jour par Renaud Dussol il y a environ 6 ans

  • Assigné à changé de Christophe LEON à Renaud Dussol

#8 Mis à jour par Renaud Dussol il y a environ 6 ans

Dans createStructure.php :

$eUrl->md5url     ="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

.
.
.

//à la fin dans // Ajustement des autres champs
\R::exec("ALTER TABLE  `app` CHANGE  `uid`  `uid` VARCHAR( 50 );");
\R::exec("ALTER TABLE `url`  CHANGE `md5url` `md5url` CHAR(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL;");
\R::exec("UPDATE `url` SET `md5url`= md5(`url`);");

// A placer avant le passage en 2048
//Le try/catch pour éviter une erreur si l'index n'existe pas. apparemment le nom de l'index est tjs le même car généré en sha1
try {
       \R::exec("ALTER TABLE `url` DROP INDEX UQ_d199ec153ccff2bb155aa543f7c4957823daa439;");
   }catch( \Exception $e) {

}
try {
          \R::exec("ALTER TABLE `url` DROP INDEX url;");
 } catch( \Exception $e) {
}

\R::exec("ALTER TABLE  `url` CHANGE  `url`  `url` VARCHAR( 2048 );"); // fixes #22746 :
 \R::exec("ALTER TABLE `url` ADD INDEX(`url`);");

Je pense qu'il faut laisser un index sur url pour la recherche.
Je ne vois pas comment on peut utiliser une recherche (notamment en regexp, pour le motif) sur du md5. Seuls les 191 premiers caractères seront indexés mais c'est largement suffisant. Par contre je suis obligé d'ajouter un DROP INDEX avant pour pas qu'il n'en rajoute un à chaque reconf... Je n'ai pas trouvé comment le faire en redbean, j'ai essayé setMeta("buildcommand.indexes" , "url") mais ça ne marchait pas...

à la fin dans l'ajout des index
remplacer :
$u->setMeta("buildcommand.unique" , "url");
par :
$u->setMeta("buildcommand.unique" , "md5url");

QUESTION : du coup si on laisse un index sur url, a-t-on besoin de toucher au code php pour le find ? Même si ce n'est que sur les 191 premiers caractères ça me parait suffisant pour la plupart des cas ?

#9 Mis à jour par Renaud Dussol il y a environ 6 ans

Dans ApiController.php

575 // $eUrl=\R::findOne( 'url', 'url = ?', array($url));
576 $eUrl=\R::findOne( 'url', 'md5url = ?', array(md5($url)));

588 $eUrl->url = $url;
589 $eUrl->md5url = md5($url);
590 $eUrl->host = $host;

#10 Mis à jour par Renaud Dussol il y a environ 6 ans

Dans AppController.php

722 // if ($url = \R::findOne('url','url = ?',[$ressource->urlComplete])) {
723 if ($url = \R::findOne('url','md5url = ?',[md5($ressource->urlComplete)])) {

744 $url->url = $ressource->urlComplete;
745 $url->md5url = md5($ressource->urlComplete);
746 $url->libelle = $ressource->libelleRessource;

#11 Mis à jour par Christophe LEON il y a environ 6 ans

  • Statut changé de Nouveau à En cours

Merci pour ces investigations
Elles sont sur une branche particulière pour que je les intègrent ?

#12 Mis à jour par Renaud Dussol il y a environ 6 ans

  • Statut changé de En cours à Résolu
  • % réalisé changé de 0 à 100

#13 Mis à jour par Arnaud FORNEROT il y a presque 6 ans

  • Version cible mis à Envole 5.10

#14 Mis à jour par Arnaud FORNEROT il y a plus de 5 ans

  • Statut changé de Résolu à Fermé

Formats disponibles : Atom PDF