[SPIP 0000142]: Epargner la base quand on fait OPTIMIZE TABLE

Une note a été ajoutée pour ce bug.

http://www.spip.net/bugs/view_bug_page.php?f_id=0000142

Rapporteur: filou
Responsable:

Projet: SPIP
Bug ID: 0000142
Catégorie: autres
Reproductibilité: quelques fois
Sévérité: majeur
Priorité: normale
Etat: nouveau

Date de soumission: 23/09/03 12:23 CEST
Dernière modification: 24/09/03 16:15 CEST

Résumé: Epargner la base quand on fait OPTIMIZE TABLE
Description:
Quand SPIP lance l'OPTIMIZE TABLE, le calcul, sur un serveur chargé, peut
prendre jusqu'à 5 minutes, et totu se bloque, MySQL se met à ramer, etc.

Deux pistes :
1) ne déclencher cette optimization que la nuit (??)
2) interdire les connexions pendant l'optimize.

autre suggestion ?

-----------------------------------------------------------------------
filou - 23/09/03 14:47 CEST
-----------------------------------------------------------------------
Florent nous disait, via la mailing-liste :

« sur des serveurs chargés, ce genre d'opération est plutôt réservé aux
administrateurs de la base de donnée. Peut-être faut-il ajouter une
option dans le configuration de SPIP permettant d'externaliser cette
opération ? (par défaut, ça reste comme ça, et lorque c'est externalisé,
c'est à l'admin de le gérer) »

Florent

-----------------------------------------------------------------------
filou - 23/09/03 14:57 CEST
-----------------------------------------------------------------------
Aïe ! Apparemment la base peut aussi se bloquer plus ou moins longtemps
quand on fait la mise à jour des popularités avec les requêtes :

UPDATE spip_articles SET popularite = GREATEST( 1, popularite ) +
0.69314718055995 * 3 WHERE id_article.....

-----------------------------------------------------------------------
JLuc - 23/09/03 16:43 CEST
-----------------------------------------------------------------------
Pistes ?
Estimer la charge instantannée du systeme avant de lancer des requetes
lourdes. Par ex, pour estimer la charge du système, chronométrer
l'exécution d'une requete-étalon. Si c'est trop long (par rapport à un
temps ou un critère plus complexe à définir ...) arrêter là.
Ou sinon sans surprise : fractionner les requêtes...

-----------------------------------------------------------------------
filou - 23/09/03 17:59 CEST
-----------------------------------------------------------------------
Pour estimer la charge, j'ai ajouté ça dans inc-public-global.php3 ; si on
est connecté et qu'on n'est pas tout seul, on pose un flag dans
ecrire/data/ et on évite de faire des gros calculs. Le flag dure une
minute max. (Je ne suis pas du tout sur que ça soit utile....)

//
----------------------------------------------------------------------------
// Taches de fond

// verifier que MySQL n'est pas surcharge (via un flag dans ecrire/data/)
if (@file_exists('ecrire/data/surcharge-mysql')) {
    spip_debug ('surcharge mysql (fichier)');
    $timeout = true;
    if (time() - @fileatime('ecrire/data/surcharge-mysql') > 60)
        @unlink('ecrire/data/surcharge-mysql');
} else {
    if ($db_ok) {
        $s = spip_query("SHOW STATUS");
        while ($r = spip_fetch_row($s))
            if (($r[0] == 'Threads_connected') AND ($r[1] > 50)) {
                spip_log ('surcharge mysql');
                $timeout = true;
                @touch('ecrire/data/surcharge-mysql');
            }
    }
}

-----------------------------------------------------------------------
filou - 24/09/03 12:52 CEST
-----------------------------------------------------------------------
Bon, j'ai mis en place tout un système pour éviter de surcharger la base
quand un fichier ecrire/data/surcharge-mysql est présent ; par ailleurs
SPIP crée ce fichier de lui-meme via le test ci-dessus.

A mon avis, je pourrais retravailler la partie "éviter de surcharger" et
la commiter.

Par contre la partie "analyse de la charge" pourrait être soit absente,
soit en option (à demander explicitement dans mes_options.php3), sachant
que l'hébergeur peut aussi décider d'avoir un cron qui crée et supprime
les fichiers ecrire/data/surcharge-mysql, et de ne pas laisser ce travail
à SPIP ?

-----------------------------------------------------------------------
antoine - 24/09/03 14:53 CEST
-----------------------------------------------------------------------
<i>A mon avis, je pourrais retravailler la partie "éviter de surcharger" et
la commiter.</i>

Honnêtement quel est l'intérêt ? Si la base est surchargée, c'est déjà
trop tard... De plus je ne vois pas pourquoi SPIP ferait le boulot de
l'hébergeur.

-----------------------------------------------------------------------
filou - 24/09/03 14:57 CEST
-----------------------------------------------------------------------
<i>Si la base est surchargée, c'est déjà trop tard... </i>

Bah non, si on arrête à ce moment-là de la solliciter trop, on lui donne
une chance de revenir sur terre avant de lui mettre en file encore plus de
requêtes. C'est comme le principe d'Ethernet (je crois : quand ça merde,
on attend, puis on redémarre).

-----------------------------------------------------------------------
antoine - 24/09/03 15:10 CEST
-----------------------------------------------------------------------
<i>Bah non, si on arrête à ce moment-là de la solliciter trop, on lui donne
une chance de revenir sur terre</i>

Mais dans la plupart des cas, ce n'est pas la base MySQL qui surcharge le
serveur, c'est le serveur qui fait ramer la base. Donc ça ne sert à rien.
Enfin, tout ça est une énorme bidouille. Les requêtes un peu grosses sont
désactivées par défaut (moteur de recherche, etc.), c'est fait pour.

-----------------------------------------------------------------------
filou - 24/09/03 15:37 CEST
-----------------------------------------------------------------------
<i>une énorme bidouille</i>

Ca ne serait pas la seule, et je peux m'arranger pour que le code soit
relativement lisible

En tous cas sur le Diplo c'est très très efficace (même si le problème du
serveur doit être réglé par ailleurs, bien entendu... au moins c'est déjà
un truc qu'on peut contrôler).

-----------------------------------------------------------------------
antoine - 24/09/03 16:15 CEST
-----------------------------------------------------------------------
La ligne suivante peut être utile :

if (@file_exists('ecrire/data/surcharge-mysql')) $timeout = true;

Pour le reste, c'est vraiment une mécanique spécifique au Diplo, à un
instant particulier. Quant à l'efficacité, heu, il est un peu tôt pour
conclure, non ?