Discussion:
Temporisation
(trop ancien pour répondre)
Pascale
2008-07-21 20:56:47 UTC
Permalink
Je dois effectuer un traitement sur une table qui contient environ 9000
enregistrements et génère autant de courriers électroniques (les
destinataires sont des associations inscrites au site, le message en
question contient une information importante). Simultanément, le contenu
d'un champ de la table est modifié pour chaque enregistrement.
Si je lance mon programme comme ça, mon hébergeur va couiner très très fort
et il aura raison parce que je vais lui saturer son serveur de courrier.
Est-ce qu'il y aurait un moyen simple de « ralentir » le programme, par une
sorte de temporisation de quelques secondes entre l'envoi de 2 messages ?

C'est une bête boucle, tout ce qu'il y a de classique :

$sel="SELECT valid,nom,theme,courriel,courrielv FROM matable";
$req = mysql_query($sel) or die('<CENTER>Erreur SQL
!'.'<br>'.mysql_error().'</CENTER>' );
while($data = mysql_fetch_array($req))
{
// traitement : modification + envoi d'e-mails
}
--
Pascale
Olivier Miakinen
2008-07-21 21:27:23 UTC
Permalink
Bonjour,
Est-ce qu'il y aurait un moyen simple de « ralentir » le programme, par une
sorte de temporisation de quelques secondes entre l'envoi de 2 messages ?
http://fr.php.net/sleep

Cordialement,
--
Olivier Miakinen
Pascale
2008-07-22 07:07:43 UTC
Permalink
Post by Olivier Miakinen
http://fr.php.net/sleep
Oui, j'ai trouvé ça entre le moment où j'ai posté et celui où le message
est paru (:
Mais ça va pas.

Si j'écris :

$sel="SELECT valid,nom,theme,courriel,courrielv FROM matable";
$req = mysql_query($sel) or die('<CENTER>Erreur SQL
!'.'<br>'.mysql_error().'</CENTER>' );
while($data = mysql_fetch_array($req))
{
$valid=$data['valid'];
$nom=$data['nom'];
$theme=$data['theme'];
$courriel'=$data['courriel'];
echo 'Le courrier pour '.$nom.' sera envoyé à l\'adresse
'.$courriel.<br />';
sleep(10);
}

et qu'il y a dans la table 11 enregistrements (c'est le cas dans ma table
de test), l'exécution du script semble prendre 11 x 10 secondes mais
s'effectuer quand même tout d'un bloc. Vrai z'ou faux ?... parce qu'avec
9000...
--
Pascale
Olivier Miakinen
2008-07-22 07:19:25 UTC
Permalink
Post by Pascale
$sel="SELECT valid,nom,theme,courriel,courrielv FROM matable";
$req = mysql_query($sel) or die('<CENTER>Erreur SQL
!'.'<br>'.mysql_error().'</CENTER>' );
while($data = mysql_fetch_array($req))
{
[...]
sleep(10);
}
et qu'il y a dans la table 11 enregistrements (c'est le cas dans ma table
de test), l'exécution du script semble prendre 11 x 10 secondes mais
s'effectuer quand même tout d'un bloc. Vrai z'ou faux ?... parce qu'avec
9000...
Je ne connais pas bien le fonctionnement des bases de données, mais je
suppose -- et tu sembles le confirmer -- que c'est le mysql_query() qui
fait tout le boulot en une seule fois sur l'ensemble de la table, alors
que mysql_fetch_array() ne fait que retourner, ligne par ligne, les
résultats déjà en mémoire.

Si tu veux limiter la requête elle-même, il est probable que tu doives
le faire dans « $sel » (je crois avoir vu quelque part une clause LIMIT)
et dans ce cas le bon forum pour en parler a toutes les chances d'être
fr.comp.applications.sgbd.
Pascale
2008-07-22 15:10:36 UTC
Permalink
Post by Olivier Miakinen
Je ne connais pas bien le fonctionnement des bases de données, mais je
suppose -- et tu sembles le confirmer -- que c'est le mysql_query() qui
fait tout le boulot en une seule fois sur l'ensemble de la table, alors
que mysql_fetch_array() ne fait que retourner, ligne par ligne, les
résultats déjà en mémoire.
Oui, c'est ça.
Post by Olivier Miakinen
Si tu veux limiter la requête elle-même, il est probable que tu doives
le faire dans « $sel » (je crois avoir vu quelque part une clause LIMIT)
et dans ce cas le bon forum pour en parler a toutes les chances d'être
fr.comp.applications.sgbd.
Oui, je pourrais le faire en passant par une table intermédiaire où
j'effacerais les enregistrements au fur et à mesure de la progression, mais
c'est plus compliqué (d'autant que je modifie un champ dans la table
d'origine).
--
Pascale
Antoine
2008-07-22 10:17:35 UTC
Permalink
Post by Pascale
$sel="SELECT valid,nom,theme,courriel,courrielv FROM matable";
$req = mysql_query($sel) or die('<CENTER>Erreur SQL
!'.'<br>'.mysql_error().'</CENTER>' );
while($data = mysql_fetch_array($req))
{
$valid=$data['valid'];
$nom=$data['nom'];
$theme=$data['theme'];
$courriel'=$data['courriel'];
echo 'Le courrier pour '.$nom.' sera envoyé à l\'adresse
'.$courriel.<br />';
sleep(10);
}
et qu'il y a dans la table 11 enregistrements (c'est le cas dans ma table
de test), l'exécution du script semble prendre 11 x 10 secondes mais
s'effectuer quand même tout d'un bloc. Vrai z'ou faux ?... parce qu'avec
9000...
Bonjour,

Peux tu préciser ce qui te donne cette impression ? Peut-être celà
vient-il du fait que la page sur laquelle tu exécute le script n'affiche
rien pendant 11x10 sec, et qu'elle envoie tout à la fin. C'est u
fonctionnement normal, PHP (Hypertext PRE-Processor) interprète tout le
code d'une page avant d'en renvoyer le contenu à ton navigateur. Je
pense d'après ton code qu'il y a bien une pause effectuée entre chaque
tour de boucle.

D'après ton code, la requête de sélection des 9000 entrées ne devrait
pas surcharger MySQL (il sert à ça). En revanche si dans ta boucle
(comme tu l'a expliqué dans ton premier message) tu fais un UPDATE sur
un champ de ta table, là il y a une montée en charge. Normalement avec
un sleep de 10 secondes, pas de souci ;)

Cordialement

Antoine
Pascale
2008-07-22 15:10:36 UTC
Permalink
Post by Olivier Miakinen
Bonjour,
Peux tu préciser ce qui te donne cette impression ? Peut-être celà
vient-il du fait que la page sur laquelle tu exécute le script
n'affiche rien pendant 11x10 sec, et qu'elle envoie tout à la fin.
C'est u fonctionnement normal, PHP (Hypertext PRE-Processor)
interprète tout le code d'une page avant d'en renvoyer le contenu à
ton navigateur. Je pense d'après ton code qu'il y a bien une pause
effectuée entre chaque tour de boucle.
Je viens de me rendre compte que tu as parfaitement raison ! Mon impression
était mauvaise ! Je viens de faire tourner le programme sur un échantillon de
11 envois. Que je fasse ou pas l'update, avec une sleep à 10 secondes, les
courriels arrivent espacés de 12 secondes.
Ce qui me fait en gros une trentaine d'heures d'envoi, mais ce n'est pas très
gênant : en principe, le programme peut être interrompu et repris n'importe quand ;
la requête d'update modifie un champ dont la valeur était obligatoirement comprise
entre 1 et 99 et passe à un chiffre compris entre 101 et 999, donc si ce champ a
une valeur supérieure à 100, l'enregistement a déjà été traité, il est ignoré.
Post by Olivier Miakinen
D'après ton code, la requête de sélection des 9000 entrées ne devrait
pas surcharger MySQL (il sert à ça). En revanche si dans ta boucle
(comme tu l'a expliqué dans ton premier message) tu fais un UPDATE sur
un champ de ta table, là il y a une montée en charge. Normalement avec
un sleep de 10 secondes, pas de souci ;)
En fait, l'UPDATE lui-même ne pose pas de problème de surcharge du serveur,
même avec 9000 enregistrements, en quelques secondes c'est plié.
Ce qui pose problème, c'est uniquement l'envoi de courriels, presque 9000 d'un
coup, je sais que le serveur de mail de mon hébergeur va saturer si je lui fais
cette vilaine blague.
Reste à savoir si le fait de mettre une commande sleep de quelques secondes
entre 2 envois suffira à ne pas le contrarier... ou s'il vaut mieux tout bêtement
mettre un LIMIT 50 dans le SELECT de départ et relancer automatiquement le programme
toutes les 3 minutes, par exemple...

Merci beaucoup à Olivier et à toi.
--
Pascale
Paul
2008-07-22 18:27:50 UTC
Permalink
Post by Pascale
.....
Reste à savoir si le fait de mettre une commande sleep de quelques secondes
entre 2 envois suffira à ne pas le contrarier... ou s'il vaut mieux tout bêtement
mettre un LIMIT 50 dans le SELECT de départ et relancer automatiquement le programme
toutes les 3 minutes, par exemple...
Si tu poses la question à ton FAI, tu auras sa réponse ! ;-)
Perso je pencherais plutôt vers la seconde solution. Ces deux phrases
pouvant être reliées par la réponse à la question : Combien de mails
simultanés maximum pour ne pas être considérée comme une spameuse ?
J'eqça.
PAUL
Anthony
2008-07-22 15:10:36 UTC
Permalink
Post by Pascale
Je dois effectuer un traitement sur une table qui contient environ 9000
enregistrements et génère autant de courriers électroniques (les
destinataires sont des associations inscrites au site, le message en
question contient une information importante). Simultanément, le contenu
d'un champ de la table est modifié pour chaque enregistrement.
Si je lance mon programme comme ça, mon hébergeur va couiner très très fort
et il aura raison parce que je vais lui saturer son serveur de courrier.
Est-ce qu'il y aurait un moyen simple de « ralentir » le programme, par une
sorte de temporisation de quelques secondes entre l'envoi de 2 messages ?
je crains que vous ne puissiez utiliser ce type de ralentissement
(sleep)... parce que votre hébergeur a plus que certainement mis une
durée d'exécution relativement basse... et votre script en pâtira.

Je vous conseille la chose suivante (avec test en amont sans envoyer les
mails bien entendu) :

Vous arrivez sur le script pour la première fois ($start=0) et envoyez X
mails ( 500 par exemple) : LIMIT $start,500

Tant que la liste complète n'est pas envoyer... un petit :
meta name en html pour relire la page au bout de X seconde... cette fois
avec $start+500 )

Du coup votre script continu d'envoyer les mails et de se « réexecuter »
X fois jusqu'à ce que tous les mails soient partis.

Anthony
Pascale
2008-07-22 18:27:50 UTC
Permalink
Post by Anthony
je crains que vous ne puissiez utiliser ce type de ralentissement
(sleep)... parce que votre hébergeur a plus que certainement mis une
durée d'exécution relativement basse... et votre script en pâtira.
Ah oui, en effet, encore un truc auquel je n'avais pas pensé.
Post by Anthony
Je vous conseille la chose suivante (avec test en amont sans envoyer
Vous arrivez sur le script pour la première fois ($start=0) et envoyez
X mails ( 500 par exemple) : LIMIT $start,500
meta name en html pour relire la page au bout de X seconde... cette
fois avec $start+500 )
Du coup votre script continu d'envoyer les mails et de se « réexecuter
» X fois jusqu'à ce que tous les mails soient partis.
Est-ce que cela revient au même que ce dont je parlais dans un message
précédent : mettre une limite (par exemple 100) dans mon SELECT de départ,
lancer l'exécution du programme dans mon navigateur, avec rechargement
automatique de la page (et donc réexécution du programme) toutes les 3 ou 4
minutes ?
--
Pascale
Olivier Miakinen
2008-07-22 18:49:06 UTC
Permalink
Post by Anthony
je crains que vous ne puissiez utiliser ce type de ralentissement
(sleep)... parce que votre hébergeur a plus que certainement mis une
durée d'exécution relativement basse... et votre script en pâtira.
Bien heureusement, il semble que non.

http://fr2.php.net/manual/fr/info.configuration.php#ini.max-execution-time
<cit.>
Le temps d'exécution maximum n'est pas affecté par des appels systèmes
tels que sleep(). Reportez-vous à la fonction set_time_limit() pour
plus de détails.
</cit.>

http://fr2.php.net/manual/fr/function.set-time-limit.php
<cit.>
Note: La fonction set_time_limit() et la directive de configuration
max_execution_time n'affectent que le temps d'exécution du script
lui-même. Tout temps passé en dehors du script, comme un appel système
utilisant system(), des opérations sur les flux, les requêtes sur base
de données, etc. n'est pas pris en compte lors du calcul de la durée
maximale d'exécution du script.
</cit.>
Pascale
2008-07-23 15:54:23 UTC
Permalink
Bien heureusement, il semble que non.[couic]
C'est bon à savoir. Même si je n'utilise pas cette fois ci la commande
sleep, elle pourrait m'être utile une autre fois et maintenant je comprends
mieux son fonctionnement.
--
Pascale
Bruno Desthuilliers
2008-07-22 15:10:36 UTC
Permalink
Post by Pascale
Je dois effectuer un traitement sur une table qui contient environ 9000
enregistrements et génère autant de courriers électroniques (les
destinataires sont des associations inscrites au site, le message en
question contient une information importante). Simultanément, le contenu
d'un champ de la table est modifié pour chaque enregistrement.
Si je lance mon programme comme ça, mon hébergeur va couiner très très fort
et il aura raison parce que je vais lui saturer son serveur de courrier.
La plupart des serveurs de courriers sortant sont capables d'envoyer un
même mail à plusieurs destinataires en même temps (en utilisant
l'entête bcc (blind carbon copy). En bref : ce n'est pas parce que tu
dois poster un mail à 9000 destinataires que tu dois envoyer 9000 mails
(à moins bien sûr que le mail soit personnalisé pour chaque destinataire).

Ceci étant, les programmes de gestion de newsletter ne manquent pas.
A-tu une raison particulière de vouloir réinventer la roue ?
Pascale
2008-07-22 18:27:50 UTC
Permalink
Post by Bruno Desthuilliers
En bref : ce n'est pas parce que tu
dois poster un mail à 9000 destinataires que tu dois envoyer 9000
mails (à moins bien sûr que le mail soit personnalisé pour chaque
destinataire).
Il l'est, et particulièrement celui-ci.
Post by Bruno Desthuilliers
Ceci étant, les programmes de gestion de newsletter ne manquent pas.
A-tu une raison particulière de vouloir réinventer la roue ?
Ben justement, c'est pas vraiment une newsletter...
--
Pascale
Bruno Desthuilliers
2008-07-22 20:46:59 UTC
Permalink
Post by Pascale
Post by Bruno Desthuilliers
En bref : ce n'est pas parce que tu
dois poster un mail à 9000 destinataires que tu dois envoyer 9000
mails (à moins bien sûr que le mail soit personnalisé pour chaque
destinataire).
Il l'est, et particulièrement celui-ci.
Alors dans ce cas, effectivement, ni bcc ni un gestionnaire de
newsletter ne pourront t'aider.
Pascale
2008-07-23 15:54:23 UTC
Permalink
Post by Bruno Desthuilliers
Alors dans ce cas, effectivement, ni bcc ni un gestionnaire de
newsletter ne pourront t'aider.
Je crois que je vais utiliser la solution toute bête de faire les envois
par paquets avec un LIMIT dans le SELECT initial, finalement, je me suis
creusé la tête pour pas grand chose : dans la mesure où, simultanément à
l'envoi, je fais une modif dans ma table qui me permet de savoir quels
enregistrements ont été traités ou pas, cette solution est simple à mettre
en œuvre - elle le serait moins si je devais passer par une table intermédiaire
que je viderais au fur et à mesure des envois.
Comme quoi, de la discussion jaillit la lumière (-: Merci à tous !
--
Pascale
John GALLET
2008-07-27 15:17:49 UTC
Permalink
Bonjour,
Post by Pascale
Si je lance mon programme comme ça, mon hébergeur va couiner très très fort
et il aura raison parce que je vais lui saturer son serveur de courrier.
Mauvais hébergeur, changer d'hébergeur. C'est bien pour ça que je loue
mes propres machines pour ne jamais être em...é.

Blague à part:
1) relire le contrat sur ce point précis
2) techniquement, n'importe quel qmail ou sendmail est capable de
prendre cette charge, surtout à l'émission. En revanche, ça ne présume
en rien du temps qui s'écoulera pour vider la queue d'émission.
Post by Pascale
Est-ce qu'il y aurait un moyen simple de « ralentir » le programme, par une
sorte de temporisation de quelques secondes entre l'envoi de 2 messages ?
Ca ne sert à rien car le serveur SMTP ne fait que mettre en file
d'attente asynchrone et enverra à son propre rythme. C'est *SON*
problème, pas celui du développeur. Ne pas oublier que le mail est
encore plus asynchrone que le protocole http.

a++;
JG
Pascale
2008-07-27 19:08:07 UTC
Permalink
Post by John GALLET
Mauvais hébergeur, changer d'hébergeur. C'est bien pour ça que je loue
mes propres machines pour ne jamais être em...é.
Il est pas mal, cet hébergeur. Je comprends ton point de vue, mais ni mon
homme ni moi ne sommes compétents pour gérer un serveur dédié (sans parler
du tarif), et le prix d'un serveur infogéré est un peu effrayant, surtout
pour des sites qui ne rapportent pas un kopek.
Post by John GALLET
1) relire le contrat sur ce point précis
2) techniquement, n'importe quel qmail ou sendmail est capable de
prendre cette charge, surtout à l'émission. En revanche, ça ne présume
en rien du temps qui s'écoulera pour vider la queue d'émission.
Bof, je vais pas les embêter plus que ça, ce sont des gens assez réactifs
quand on a un problème, donc je vais faire mes envois par paquets de 50 et
voilà tout.
Post by John GALLET
Ca ne sert à rien car le serveur SMTP ne fait que mettre en file
d'attente asynchrone et enverra à son propre rythme. C'est *SON*
problème, pas celui du développeur. Ne pas oublier que le mail est
encore plus asynchrone que le protocole http.
C'est vrai.
--
Pascale
Bruno Desthuilliers
2008-07-27 19:49:04 UTC
Permalink
Post by Pascale
Post by John GALLET
Mauvais hébergeur, changer d'hébergeur. C'est bien pour ça que je loue
mes propres machines pour ne jamais être em...é.
Il est pas mal, cet hébergeur. Je comprends ton point de vue, mais ni mon
homme ni moi ne sommes compétents pour gérer un serveur dédié (sans parler
du tarif),
dedibox : une trentaine d'euro par mois.

Evidemment, ça ne règle pas le problème du paramétrage et de
l'administration su serveur...
Pascale
2008-07-28 11:18:16 UTC
Permalink
Post by Bruno Desthuilliers
dedibox : une trentaine d'euro par mois.
Evidemment, ça ne règle pas le problème du paramétrage et de
l'administration su serveur...
Oui. Il existe aussi des serveurs infogérés, mais c'est assez chérot.
Il faut d'ailleurs que je regarde de plus près l'offre de Gandi, ils
proposent aussi de l'hébergement.
--
Pascale
Continuer la lecture sur narkive:
Loading...