Version complète: sur le forum Webmaster Hub : Principe de base "tampon"
Webmaster Hub > Création et exploitation de Sites Internet > Les langages du Net > PHP
bobdeo
Bonjour,

J'ai un gros process de mise à jour d'un site. Il se décompose comme ceci :
- copie de gros fichiers XML sur le serveur (env 100 Mo au total)
- import des xml par un parsing avec php dans une table temporaire "pt_products_temp" --> dure 10 min
- on vide la table "pt_products" (table de production)
- on copie "pt_products_temp" dans "pt_products" --> dure quelques secondes

Mon code :
CODE
    // on vide la table de prod
    $sql = "TRUNCATE TABLE `pt_products`";
    $resultat = mysql_query($sql);
    
    // on copie les données
    $sql = 'INSERT INTO `pt_products` SELECT * FROM `pt_products_temp`;';
    $resultat = mysql_query($sql);
    
    // on vide la table temp
    $sql = "TRUNCATE TABLE `pt_products_temp`";
    $resultat = mysql_query($sql);


Ca se passe plutôt bien sauf que des erreurs apparaissent en front :

CODE
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 21

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 26


Pourtant, un coup de "Réparer les table" dans PhpMyAdmin et c'est reparti...

Savez-vous pourquoi ? Existerait-il une solution plus fiable (en intervenant que sur le script d'import) ?

Merci pour votre aide
binarygirl
Ca aiderait si pouviez rajouter du code de debug pour afficher l'erreur renvoyée par mysql smile.gif
bobdeo
Merci pour votre réponse.

CITATION(binarygirl @ dimanche 19 août 2007 à 17:30) *
code de debug


Qu'est-ce que c'est ? unsure.gif
iNCiTE Web
Du code supplémentaire pour debugger, c'est-à-dire pister les erreurs, par exemple :
CODE
echo mysql_error();
bobdeo
Je ne connaissais pas ! merci

Résultat : Can't find FULLTEXT index matching the column list
iNCiTE Web
Tes tables sont en MyISAM ou InnoDB ?
bobdeo
MyISAM
iNCiTE Web
Tu peux coller ici les lignes 21 et 26 de database.php ?

A priori il y aurait un problème d'index, mais comme je n'ai pas tout le code... il manquerait un index FULLTEXT sur toutes les colonnes de la recherche...
bobdeo
Merci pour ton aide

De la ligne 21 à 26 :
CODE
    while($row = mysql_fetch_array($result,MYSQL_ASSOC))
    {
      $rows[] = $row;
    }

    return mysql_num_rows($result);
iNCiTE Web
Mouais ça va pas suffire... il faudrait la portion de code, surtout celle d'avant qui compose la requête
bobdeo
Voilà tout le fichier :

CODE
<?php

  function database_querySelect($sql,&$rows)
  {
    global $config_databaseServer;

    global $config_databaseName;

    global $config_databaseUsername;

    global $config_databasePassword;

    $link = _AT_mysql_connect($config_databaseServer,$config_databaseUsername,$config_databasePassword);

    @mysql_select_db($config_databaseName,$link);

    $result = mysql_query($sql,$link);

    $rows = array();

    while($row = mysql_fetch_array($result,MYSQL_ASSOC))
    {
      $rows[] = $row;
    }

    return mysql_num_rows($result);
  }

  function database_queryModify($sql,&$insertId)
  {
    global $config_databaseServer;

    global $config_databaseName;

    global $config_databaseUsername;

    global $config_databasePassword;

    $link = _AT_mysql_connect($config_databaseServer,$config_databaseUsername,$config_databasePassword);

    @mysql_select_db($config_databaseName,$link);

    $result = mysql_query($sql,$link);

    $insertId = mysql_insert_id();

    return mysql_affected_rows();
  }

  function database_safe($text)
  {
    return mysql_escape_string($text);
  }
?>


Je ne sais pas si tu arriveras à quelque chose. Existe-il un moyen de "refaire" l'index en fin d'import (puisque c'est lui qui met la zone)...
iNCiTE Web
Bon ça c'est la fonction, mais il manque $sql pour voir quelle est la requête... donc je sais pas quels champs ni quelles tables sont concernées.
Rajoute :
CODE
if ( mysql_error() ) echo $sql;
bobdeo
Voici un exemple de la requête :

CODE
SELECT * , MIN( price ) AS minPrice, MAX( price ) AS maxPrice, COUNT( id ) AS numMerchants, MATCH name AGAINST ('Hitachi DZ HS500E') AS relevance FROM `pt_products` WHERE category = 'Camescopes' AND MATCH name AGAINST ('Hitachi DZ HS500E') AND name <> 'Hitachi DZ HS500E' GROUP BY name ORDER BY relevance LIMIT 5


Merci
Occi
C'est au niveau du MATCH ... AGAINST ('...')

Essaye de créer un Fulltext sur le champ de la table "name" (dans ton exemple) où tu recherches avec ça ...
Nsg
Bonjour,

CITATION(bobdeo @ dimanche 19 août 2007 à 14:35) *
J'ai un gros process de mise à jour d'un site. Il se décompose comme ceci :
- copie de gros fichiers XML sur le serveur (env 100 Mo au total)
- import des xml par un parsing avec php dans une table temporaire "pt_products_temp" --> dure 10 min

si ce n'est pas déjà fait essayes de passer directement du xml à une requête sql (ou un fichier cvs)
xml -> confrontation à un xsl ou dtd pour validation -> transformation xslt -> sortie sql ou texte
reste ensuite à donner directement la commande générée à mysql (ou faire un load data infile)
le tout placé dans un bash sh (éventuellement appelé par php ou cron)

il y a par exemple xsltproc comme processeur xml utilisable en ligne de commande (et donc via exec de php)

il faut bien sûr avoir les droit suffisant sur l'hébergement mais il y a de grande chance que xsltproc + "load data infile" aille plus vite que php/extention+requête ; et sur 10 minutes de traitement la différence peut être sensible. (maintenant si c'est à faire tous les 36 du mois à 3h du mat c'est peut-être pas la priorité)

CITATION
- on vide la table "pt_products" (table de production)
- on copie "pt_products_temp" dans "pt_products" --> dure quelques secondes

Mon code :
CODE
    // on vide la table de prod
    $sql = "TRUNCATE TABLE `pt_products`";
    $resultat = mysql_query($sql);
    
    // on copie les données
    $sql = 'INSERT INTO `pt_products` SELECT * FROM `pt_products_temp`;';
    $resultat = mysql_query($sql);
    
    // on vide la table temp
    $sql = "TRUNCATE TABLE `pt_products_temp`";
    $resultat = mysql_query($sql);

il semble que TRUNCATE ne prenne pas en compte les transactions en cours, donc un LOCK serait adéquat (et peut être déjà en oeuvre)
et si un LOCK/UNLOCK est nécessaire, peut être que quelque secondes peuvent être gagnées en évitant le SELECT et en interchangeant les tables
après traitement dex xml > `pt_products_temp`:

CODE
LOCK TABLES `pt_products` WRITE, `pt_products_temp` WRITE`;
RENAME TABLE `pt_products` TO `pt_backup`,
             `pt_products_temp` TO `pt_products`,
             `pt_backup` TO `pt_products_temp`;
TRUNCATE `pt_products_temp`;
UNLOCK TABLES `pt_products`, `pt_products_temp`;

... à voir si le temps d'indisponibilité est plus court (temps total éventuellement plus long car le LOCK va attendre que les transactions en cours se terminent)


CITATION
Ca se passe plutôt bien sauf que des erreurs apparaissent en front :

CODE
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 21

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 26

comme ça a été dit il y a un problème d'index après que la table ait été supprimée puis recrée avec TRUNCATE
après quelques recherche j'ai trouvé entre autres ce post qui pourrait expliquer l'erreur sur certaines versions de mysql

il semble que ce soit une histoire d'index non "activés" à la recréation qui suit le TRUNCATE, ceci quand ces index ne sont pas PRIMARY ou UNIQUE
donc le MATCH qui nécessite un index ne fonctionne plus

la solution serait à priori de modifier tes index, car les réactiver avec ANALYSE ou OPTIMIZE TABLE tout de suite après le TRUNCATE ne fonctionnera sans doute pas ("table already up to date...") et le faire après l'insertion de toute les données prendra plus de temps (après un premier enregistrement ça devrait toutefois fonctionner)

là aussi c'est à tester...
il y a aussi la solution d'upgrader mysql

CITATION
Pourtant, un coup de "Réparer les table" dans PhpMyAdmin et c'est reparti...

Savez-vous pourquoi ? Existerait-il une solution plus fiable (en intervenant que sur le script d'import) ?

cf au dessus, la commande utilisée par le "Réparer les table" de PhpMyAdmin reconstruit les index entre-autres

A+
Nsg
Occi
Intéressant ... Et du coup quand on sauvegarde sa base de données via phpMyadmin ça fait le même effet que le TRUNCATE (suppression du FULLTEXT) ?
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.