<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>La Case de l&#039;Oncle Tom &#187; MySQL</title>
	<atom:link href="http://case.oncle-tom.net/tag/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://case.oncle-tom.net</link>
	<description>Développement Web, bonnes pratiques et performances</description>
	<lastBuildDate>Sun, 25 Dec 2011 19:33:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="search"
           href="http://case.oncle-tom.net/opensearch"
           type="application/opensearchdescription+xml"
           title="Content Search" />		<item>
		<title>Configuration d&#8217;Apache, MySQL et PHP à base de liens symboliques</title>
		<link>http://case.oncle-tom.net/2008/configuration-apache-mysql-php-symlinks/</link>
		<comments>http://case.oncle-tom.net/2008/configuration-apache-mysql-php-symlinks/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 06:00:50 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apparmor]]></category>
		<category><![CDATA[bonne pratique]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symlink]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1198</guid>
		<description><![CDATA[J&#8217;ai récemment passé mon poste de développement de Debian Testing vers Ubuntu 8.10. Comme toute installation from scratch, il faut passer par la case configuration. J&#8217;ai déjà expliqué comment modifier l&#8217;emplacement des données d&#8217;un serveur MySQL mais cette fois-ci on va aller encore plus loin : on ne va pas toucher aux fichiers de configuration [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai récemment passé mon poste de développement de Debian Testing vers Ubuntu 8.10. Comme toute installation <em>from scratch</em>, il faut passer par la case configuration.</p>
<p><img class="aligncenter size-full wp-image-1247" title="Configuration PHP personnalisée" src="http://case.oncle-tom.net/images/2008/12/php-custom.png" alt="" width="499" height="64" /></p>
<p>J&#8217;ai déjà expliqué comment <a href="http://case.oncle-tom.net/2008/05/04/modifier-emplacement-donnees-serveur-mysql/">modifier l&#8217;emplacement des données d&#8217;un serveur MySQL</a> mais cette fois-ci on va aller encore plus loin :</p>
<ul>
<li>on ne va pas toucher aux fichiers de configuration par défaut</li>
<li>on va pouvoir conserver toute notre configuration sur une partition séparée</li>
<li>on va être tranquille pour les éventuelles futures réinstallations</li>
</ul>
<p>C&#8217;est pas très compliqué à mettre en œuvre et au final, tout le monde y gagne !</p>
<p><span id="more-1198"></span></p>
<h3>Organisation du répertoire /home</h3>
<p>Le titre de l&#8217;article le suggère bien, cet article se consacre à la configuration des serveurs et programmes suivants :</p>
<ul>
<li>Apache 2</li>
<li><acronym title="Pre-Hypertext Processing">PHP</acronym> 5</li>
<li>MySQL 5</li>
<li>AppArmor (installé et activé par défaut depuis Ubuntu 8.04)</li>
</ul>
<p>Pour des raisons évidentes de facilité, j&#8217;ai donc créé un répertoire qui rassemble toutes mes configurations spécifiques. En voici son arborescence :</p>
<ul>
<li><strong>~/config</strong>
<ul>
<li>/<em>apache2</em>
<ul>
<li>sites-available
<ul>
<li>000-default-custom</li>
<li>local.monprojet.com</li>
<li>etc.</li>
</ul>
</li>
</ul>
</li>
<li>/<em>apparmor</em>
<ul>
<li>usr.sbin.mysqld-custom</li>
</ul>
</li>
<li>/<em>mysql</em>
<ul>
<li>my-custom.cnf</li>
</ul>
</li>
<li>/<em>php5</em>
<ul>
<li>php-custom.ini</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Nous écrirons dans ces fichiers uniquement les points de configuration que l&#8217;on souhaite adapter. C&#8217;est plus simple à maintenir. Qui plus est, si les fichiers de configuration sont mis à jour par leur serveur respectif, nos fichiers resteront à l&#8217;abri.</p>
<p>Un des <em>moto</em> de Debian c&#8217;est la <strong>configuration à base de fichiers</strong>. Vous trouverez régulièrement des répertoires ayant un nom suivant le motif <em>application.d</em>. Donc plutôt que d&#8217;avoir 1 seul fichier de configuration, on a 1 fichier initial plus des configurations additionnelles dans ces fameux répertoires &laquo;&nbsp;.d&nbsp;&raquo;.</p>
<h3>Configuration d&#8217;Apache</h3>
<p><img class="aligncenter size-full wp-image-1246" title="Logo Apache" src="http://case.oncle-tom.net/images/2008/12/apache-logo.gif" alt="" width="248" height="70" /></p>
<p>Pour Apache la démarche est la suivante :</p>
<ol>
<li>créer les <em>Virtual Host</em> dans son répertoire personnel</li>
<li>lier les fichiers dans <em>sites-available</em></li>
<li>activer les sites à l&#8217;aide de la commande <em>a2ensite</em></li>
<li>recharger Apache</li>
</ol>
<p>La seule étape par rapport à d&#8217;habitude c&#8217;est qu&#8217;on ne crée par les <em>Virtual Host</em> directement dans /etc/apache2/sites-available et qu&#8217;on les lie depuis notre répertoire personnel.<br />
Admettons que je souhaite créer un <em>Virtual Host</em> pour une instance locale de mon blog. Je vais procéder ainsi :</p>
<ol>
<li><kbd>gedit ~/conf/apache2/sites-available/local.case.oncle-tom.net</kbd><br />
J&#8217;y ai placé une configuration somme toute minimaliste :</p>
<pre><code class="text">&lt;VirtualHost *:80&gt;
ServerName local.case.oncle-tom.net
DocumentRoot /home/oncletom/workspace/case.oncle-tom.net
ErrorLog /var/log/apache2/error.case.oncle-tom.net.log
LogLevel warn
CustomLog /var/log/apache2/access.case.oncle-tom.net.log combined
ServerSignature On
&lt;/VirtualHost&gt;</code></pre>
</li>
<li><kbd>sudo ln -s ~/conf/apache2/sites-available/local.case.oncle-tom.net /etc/apache2/sites-available/local.case.oncle-tom.net</kbd></li>
<li><kbd>sudo a2ensite local.case.oncle-tom.net</kbd></li>
<li><kbd>sudo service apache2 reload</kbd></li>
</ol>
<p>On se fendra de l&#8217;ajout d&#8217;un hôte local dans le fichiers <em>hosts</em> pour coller au plus près à l&#8217;instance de production. Toutefois je ne connais pas d&#8217;autre moyen que de modifier le fichier d&#8217;origine :-/ Si vous avez une solution je suis preneur.</p>
<h3>Configuration de MySQL</h3>
<p><img class="aligncenter size-full wp-image-744" title="Logo MySQL" src="http://case.oncle-tom.net/images/2007/08/powered-by-mysql-167x86.png" alt="" width="167" height="86" /></p>
<p>Pour MySQL c&#8217;est un peu plus compliqué car on va également en profiter pour déplacer l&#8217;emplacement par défaut des données. Pourquoi ? Pour les placer sur une partition qui ne craindra pas les formattages et les réinstallation système.<br />
Si vous aviez déjà suivi ma <a href="http://case.oncle-tom.net/2008/05/04/modifier-emplacement-donnees-serveur-mysql/">procédure de déplacement des données MySQL</a> : oubliez là. Celle-ci est largement plus aboutie.</p>
<p>Avant de se jeter à corps perdu dans les manipulations, voici la démarche entreprise :</p>
<ol>
<li>créer le fichier de configuration MySQL</li>
<li>créer le répertoire qui accueillera les données MySQL</li>
<li>lier la base <em>mysql</em> d&#8217;origine</li>
<li>modifier la configuration d&#8217;AppArmor</li>
<li>recharger la configuration des serveurs AppArmor et MySQL</li>
</ol>
<p>C&#8217;est déjà un peu plus long mais là encore, il n&#8217;y a pas grand chose à faire en fin de compte :</p>
<ol>
<li><kbd>gedit ~/conf/mysql/my-custom.cnf</kbd><br />
On y indique le nouvel emplacement de ses données MySQL :</p>
<pre><code class="text">[mysqld]
datadir            = /home/oncletom/Apps/mysql</code></pre>
</li>
<li><kbd>mkdir /home/oncletom/Apps/mysql<br />
sudo chown mysql:mysql /home/oncletom/Apps/mysql</kbd></li>
<li><kbd>ln -s /var/lib/mysql/mysql /home/oncletom/Apps/mysql/mysql</kbd></li>
<li><kbd>sudo gedit /etc/apparmor.d/usr.bin.mysql</kbd><br />
J&#8217;y ai remplacé</p>
<pre><code class="text">/var/lib/mysql/ r,
/var/lib/mysql/** rwk,</code></pre>
<p>par l&#8217;ancien chemin + le nouvel emplacement des données MySQL</p>
<pre><code class="text">/var/lib/mysql/ r,
/var/lib/mysql/** rwk,
/home/oncletom/Apps/mysql/ r,
/home/oncletom/Apps/mysql/** rwk,</code></pre>
</li>
<li><kbd>sudo service apparmor reload &amp;&amp; sudo service mysql reload</kbd></li>
</ol>
<p>Si vous avez bien suivi toutes mes explications, vous vous demanderez pourquoi j&#8217;ai modifié le profil existant de MySQL dans AppArmor au lieu de lier un nouveau profil ?<br />
Je me suis rendu compte qu&#8217;au démarrage de l&#8217;<acronym title="Operating System">OS</acronym>, <strong>AppArmor ne chargeait pas le profil personnalisé</strong> et bloquait le démarrage de MySQL. J&#8217;ai créé un <a href="http://ubuntuforums.org/showthread.php?t=977830">sujet sur Ubuntu Forums</a> après une lecture de la <a href="https://help.ubuntu.com/community/AppArmor">documentation AppArmor</a> mais pas de nouvelles. Là aussi je suis preneur car en relançant les serveurs à la main, tout fonctionne.</p>
<p>Ensuite à vous de repeupler vos bases de données à partir d&#8217;un dump. Si vous procédez à un déplacement des répertoires, n&#8217;oubliez pas de tout préserver : propriétaire et permissions ! Ça se passe avec l&#8217;option <em>-a</em> de <em>cp</em> par exemple.</p>
<h3>Configuration de <acronym title="Pre-Hypertext Processing">PHP</acronym></h3>
<p><img class="aligncenter size-full wp-image-1245" title="Logo PHP" src="http://case.oncle-tom.net/images/2008/12/php.gif" alt="" width="120" height="67" /></p>
<p>Fort heureusement pour <acronym title="Pre-Hypertext Processing">PHP</acronym> c&#8217;est plus simple puisqu&#8217;il n&#8217;y a qu&#8217;un seul petit lien symbolique à faire.<br />
À noter que la configuration modifiée sera répercutée sur toutes les configurations de <acronym title="Pre-Hypertext Processing">PHP</acronym>, que ça soit pour Apache, en CLI ou <acronym title="Common Gateway Interface">CGI</acronym>.</p>
<ol>
<li><kbd>gedit ~/conf/php/my-custom.ini</kbd><br />
J&#8217;ai ai mis par exemple :</p>
<pre><code class="text">memory_limit = 64M</code></pre>
</li>
<li><kbd>sudo ln -s ~/conf/php/my-custom.ini /etc/php5/conf.d/my-custom.ini</kbd></li>
</ol>
<p>Et voilà c&#8217;est tout pour <acronym title="Pre-Hypertext Processing">PHP</acronym>. Il faut bien entendu recharger votre serveur Web (Apache ou Lighttpd par exemple) pour qu&#8217;ils prennent en compte la modification.</p>
<h3>Conclusion</h3>
<p>J&#8217;ai déjà appliqué cette méthode par 2 fois et que dire si ce n&#8217;est que tout va plus vite ainsi !<br />
Vos fichiers de configuration restent accessibles depuis votre gestionnaire de fichiers (pas besoin de passer en <em>sudo</em> pour sauvegarder les changements). Ils sont préservés de toute réinstallation impromptue.</p>
<p><strong>Vous ne touchez que de manière minimaliste aux fichiers de configuration d&#8217;origine</strong> :</p>
<ul>
<li>/etc/hosts pour ajouter un nom d&#8217;hôte (utile seulement si vous ne souhaitez pas utiliser <em>localhost</em>)</li>
<li>/etc/apparmor.d/usr.bin.mysql pour la raison évoquée plus haut &#8230; sinon on s&#8217;en serait passé</li>
</ul>
<p>J&#8217;ai cherché à faire pareil avec <em>phpmyadmin</em> mais il ne semble pas y avoir de mécanisme de ce type. Dommage.</p>
<p>J&#8217;imagine qu&#8217;il doit y avoir des moyens similaires avec d&#8217;autres serveurs et d&#8217;autres langages. Vous procédez à un reparamétrage systématique ou bien vous utilisez une technique de ce genre ?</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/configuration-apache-mysql-php-symlinks/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Modifier l&#8217;emplacement des données d&#8217;un serveur MySQL</title>
		<link>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/</link>
		<comments>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/#comments</comments>
		<pubDate>Sun, 04 May 2008 09:25:57 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[apparmor]]></category>
		<category><![CDATA[datadir]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql5]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=908</guid>
		<description><![CDATA[L&#8217;installation par défaut d&#8217;un serveur MySQL est suffisante pour être opérationnel dans la minute qui suit. Elle ne facilite en revanche pas la maintenance en laissant le répertoire contenant vos bases de données et tables hors de portée. L&#8217;intérêt de choisir soi-même l&#8217;emplacement de ce répertoire, le datadir, est double : regrouper les données en [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/08/powered-by-mysql-167x86.png" alt="Logo MySQL" /></p>
<p>L&#8217;installation par défaut d&#8217;un serveur MySQL est suffisante pour être opérationnel dans la minute qui suit. Elle ne facilite en revanche pas la maintenance en laissant le répertoire contenant vos bases de données et tables hors de portée.</p>
<p>L&#8217;intérêt de choisir soi-même l&#8217;emplacement de ce répertoire, le <em>datadir</em>, est double :</p>
<ul>
<li><strong>regrouper les données en un endroit connu</strong> (facilite les sauvegardes)</li>
<li>utiliser le partitionnement du disque pour <strong>ne pas avoir à craindre une perte de données</strong> en cas de réinstallation du système (facilite la maintenance)</li>
</ul>
<p>Nous allons voir comment procéder à ce changement tout en adaptant les sécurités des systèmes tels que <a href="http://fedoraproject.org/wiki/SELinux">SELinux</a> et <a href="http://www.novell.com/linux/security/apparmor/">AppArmor</a>. Ces derniers empêcheront en effet le serveur de démarrer.</p>
<p><span id="more-908"></span></p>
<p><strong class="highlight">Remarque importante</strong> : j&#8217;ai publié une <a href="http://case.oncle-tom.net/2008/12/11/configuration-apache-mysql-php-symlinks/">version améliorée du déplacement des données d&#8217;un serveur MySQL</a>. Je la recommande par rapport à cet article : elle implique moins de manipulations et est plus propre.</p>
<h3>Quelques généralités avant de commencer</h3>
<p>Quitte à changer l&#8217;emplacement du <em>datadir</em>, autant le déplacer sur une partition qui ne sera pas effacé lors de la réinstallation de votre système d&#8217;exploitation, que ça soit du Linux, MacOS ou Windows.</p>
<p>Personnellement, sous Ubuntu/Debian, je crée un répertoire dans /home qui s&#8217;appelle mysql. Mon répertoire /home est bien entendu monté sur une partition différente. Si ce n&#8217;est pas le cas chez vous, pensez à <a href="http://doc.ubuntu-fr.org/installation/deplacer_home">déplacer votre /home</a>.</p>
<pre><code class="shell">sudo mkdir /home/mysql
sudo chown mysql:mysql /home/mysql</code></pre>
<p>Enfin, dernier détail à connaître : l&#8217;emplacement de vos données MySQL :</p>
<ul>
<li>sous Linux, généralement : <code>/var/lib/mysql</code></li>
<li>sous Windows, avec WAMP : <code>C:Program FilesWampmysqldata</code></li>
</ul>
<h3>Méthode 1 : modifier la configuration MySQL</h3>
<p>C&#8217;est probablement la <strong>méthode la plus simple</strong> mais elle a l&#8217;inconvénient d&#8217;avoir à modifier un fichier de configuration. Il faut donc modifier la propriété <em>datadir</em> de votre <a href="http://dev.mysql.com/doc/refman/5.1/en/option-files.html">fichier de configuration MySQL</a> :</p>
<ul>
<li>sous Linux, généralement : <code>/etc/mysql/my.cnf</code></li>
<li>sous Windows, avec WAMP : <code>C:Program FilesWampmysqlconfmy.ini</code></li>
</ul>
<p>Dans ce fichier se trouve une section consacrée à la configuration générale du serveur mysql (<em>mysqld</em> pour <em>mysql daemon</em>) :</p>
<pre><code class="text">[mysqld]
user            = mysql
port            = 3306
basedir         = /usr
<strong>datadir</strong>         = <strong>/var/lib/mysql</strong>
tmpdir          = /tmp</code></pre>
<p>J&#8217;ai mis en gras la ligne qui nous intéresse, à savoir le <em>datadir</em>.<br />
Quelle valeur mettre ? Celle de l&#8217;emplacement souhaité pour vos données. Dans mon cas ça aurait été /home/mysql :</p>
<pre><code class="text"><strong>datadir</strong>         = <strong>/home/mysql</strong></code></pre>
<p>Vous vous assurerez d&#8217;avoir bien stoppé le service MySQL, d&#8217;avoir copié/collé vos données de l&#8217;ancien emplacement vers le nouveau et enfin de redémarrer MySQL. C&#8217;est seulement en cas de réussite que vous pourrez supprimer l&#8217;ancien répertoire <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<pre><code class="shell">sudo -s
/etc/init.d/mysql stop
cp -pr /var/lib/mysql/* /home/mysql
/etc/init.d/mysql start</code></pre>
<h3>Méthode 2 : utilisation d&#8217;un lien symbolique</h3>
<p>La <a href="http://dev.mysql.com/doc/refman/5.1/en/symbolic-links.html">documentation de MySQL explique l&#8217;utilisation des liens symboliques</a> pour tout, une base de données précises voire même les tables. Ceci dit nous allons voir l&#8217;exemple global : on déplace tout.</p>
<p>Concrètement cette méthode consiste à :</p>
<ol>
<li>stopper le service MySQL</li>
<li>déplacer le répertoire de données (au cas où)</li>
<li>créer le lien symbolique</li>
<li>copier les données dans le nouvel emplacement</li>
<li>relancer le service MySQL</li>
</ol>
<p>Concrètement, ça se traduit comme ceci :</p>
<pre><code class="shell">sudo -s
mv /var/lib/mysql /var/lib/mysql-old
ln -s /home/mysql /var/lib/mysql
cp -pr /var/lib/mysql-old/* /home/mysql
/etc/init.d/mysqld start</code></pre>
<p>Là encore, supprimez la copie de vos données (répertoire mysql-old) seulement en cas de succès. Ça facilite les retours en arrière en cas de pépin.</p>
<h3>Cas particulier : systèmes employant AppArmor ou SELinux</h3>
<p>Il y a cependant un hic possible si vous utilisez une distribution Fedora ou Ubuntu, surtout depuis sa version <a href="http://doc.ubuntu-fr.org/hardy">Hardy Heron (8.04)</a>. Celle-ci intègre une sécurité pour éviter à certains services critiques d&#8217;être altérés par une manipulation extérieure &#8230; comme la notre.</p>
<p>Il faut savoir que les 2 méthodes du haut échoueront si vous rentrez dans ce cas de figure : le <strong>service MySQL ne démarre pas</strong>.<br />
Pas de panique, il y a juste un fichier à modifier : <code>/etc/apparmor.d/usr.sbin.mysqld</code>. Il y a un passage ressemblant à ceci, <em>dans le cas d&#8217;AppArmor et Ubuntu</em> :</p>
<pre><code class="text">/etc/mysql/*.pem r,
/etc/mysql/conf.d/ r,
/etc/mysql/conf.d/* r,
/etc/mysql/my.cnf r,
/usr/sbin/mysqld mr,
/usr/share/mysql/** r,
<strong>/var/lib/mysql/</strong> r,
<strong>/var/lib/mysql/**</strong> rwk,
/var/log/mysql/ r,
/var/log/mysql/* rw,
/var/run/mysqld/mysqld.pid w,
/var/run/mysqld/mysqld.sock w,</code></pre>
<p>Vous voyez le loup venir. Il suffit de remplacer les occurences de /var/lib/mysql par le chemin de votre nouvel emplacement, /home/mysql dans notre cas :</p>
<pre><code class="text"><strong>/home/mysql/</strong> r,
<strong>/home/mysql/**</strong> rwk,</code></pre>
<p>La raison de cette modification est presque simple : AppArmor ne suit pas les liens symboliques. <strong>Il considère que /var/lib/mysql est différent de /home/mysql</strong> et que ce dernier ne concerne pas le service mysqld.<br />
<strong>Notre modification évite ce blocage</strong> et permet du même coup au serveur MySQL de démarrer ; les échecs étant dus au fait que le serveur ne trouvait pas de base à charger (dont la sienne, <em>mysql</em>).</p>
<p>Pour terminer, on peut relancer les 2 services, apparmor et mysqld :</p>
<pre><code class="shell">sudo /etc/init.d/apparmor restart
sudo /etc/init.d/mysqld restart</code></pre>
<h3>Conclusion</h3>
<p>Nous avons vu 2 méthodes pour rendre sa <strong>gestion des bases de données plus souple et plus sure</strong>. En cas de défaillance système &#8211; ça arrive même aux meilleurs &#8211; il faut pouvoir le réinstaller sans craindre de perdre des données vitales. Et les bases de données le sont.</p>
<p>On peut aussi constater que les <strong>nouveaux services de protection peuvent compliquer la vie</strong> si on ne les sait pas actifs et si on ne comprend pas leur fonctionnement. J&#8217;ai passé plusieurs heures à comprendre pourquoi le serveur MySQL ne se relançait pas alors qu&#8217;il me semblait avoir effectué la même manipulation sur les précédentes versions d&#8217;Ubuntu.</p>
<p>N&#8217;hésitez pas à partager votre méthode ou apporter vos suggestions sur votre gestion des <em>datadir</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/modifier-emplacement-donnees-serveur-mysql/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Google, ange et démon : faut-il lui confier notre vie numérique ?</title>
		<link>http://case.oncle-tom.net/2008/google-ange-demon-vie-numerique/</link>
		<comments>http://case.oncle-tom.net/2008/google-ange-demon-vie-numerique/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 06:00:27 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Personnel]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google adsense]]></category>
		<category><![CDATA[google reader]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[wine]]></category>
		<category><![CDATA[yahoo]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2008/03/11/google-ange-demon-vie-numerique/</guid>
		<description><![CDATA[Google est une société à la fois adulée et pointée du doigt. La moindre nouveauté résonne sur l&#8217;étendue du Web, louée par ses défenseurs, critiquée par ses détracteurs. Au-delà de ces querelles insipides et totalement subjectives, qu&#8217;est-on en droit de penser de Google ? Aujourd&#8217;hui nous confions notre vie à Google avec plus ou moins [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2008/03/google-logo.gif' alt='Logo Google' /></p>
<p><a href="http://www.google.com/">Google</a> est une société à la fois adulée et pointée du doigt. La moindre nouveauté résonne sur l&#8217;étendue du Web, louée par ses défenseurs, critiquée par ses détracteurs.<br />
Au-delà de ces querelles insipides et totalement subjectives, <strong>qu&#8217;est-on en droit de penser de Google</strong> ?</p>
<p>Aujourd&#8217;hui <strong>nous confions notre vie à Google avec plus ou moins de visibilité</strong> : données personnelles, emails, mots de passe, habitudes comportementales, organisation professionnelle et j&#8217;en passe. Est-ce parce que c&#8217;est écrit Google que l&#8217;on peut dormir tranquille ?<br />
<span id="more-882"></span></p>
<h3>Quels intérêts à confier sa vie à Google ?</h3>
<h4>Des services qui justifient leur taux d&#8217;adoption</h4>
<p>Rendons à César ce qui appartient à César : de <strong>nombreux services Google sont exemplaires et méritent d&#8217;être utilisés</strong>. Difficile de ne pas faire état du moteur de recherche, LE service qui a révélé Google au monde entier et sur lequel il a basé tout le reste de sa stratégie. Il n&#8217;est peut-être pas pertinent sur toutes les recherches (d&#8217;où l&#8217;intérêt d&#8217;avoir un choix de moteurs) mais il faut bien avouer que ses réponses cadrent bien avec les requêtes.<br />
Bilan des courses ? Un <strong>moteur employé à hauteur de 90% en Europe</strong> ; chiffre qui devrait être atteint fin 2008/début 2009 aux États-Unis.</p>
<p>Comment continuer sans parler de <a href="http://mail.google.com/">Gmail</a> (emails), <a href="http://maps.google.com/">Google Maps</a> (cartographie et itinéraires), <a href="http://calendar.google.com/">Google Calendar</a> (agenda), <a href="http://www.google.com/reader">Google Reader</a> (lecteur de contenus syndiqués), <a href="http://www.google.com/a/">Google Apps</a> (solution collaborative pour son propre nom de domaine), <a href="http://www.blogger.com/">Blogger</a> (blogs) et <a href="http://www.google.com/analytics/">Google Analytics</a> (mesure d&#8217;audience), entre autre.</p>
<p>Tous ces services, on aurait du mal à les quitter du jour au lendemain, d&#8217;autant plus qu&#8217;ils sont gratuits. C&#8217;est peut-être à ça que l&#8217;on reconnaît un produit indispensable :<strong> il améliore notre quotidien et ne représente pas une contrainte</strong>.</p>
<h4>Des services tournés vers l&#8217;utilisateur</h4>
<p style="text-align:center"><a href="http://www.fredcavazza.net/wp/wp-content/uploads/Q1-08/Gmail2.jpg"><img src="http://www.fredcavazza.net/wp/wp-content/uploads/Q1-08/Gmail2.jpg" alt="Simplexité et Gmail" /></a></p>
<p>En plus d&#8217;excellents services, Google se paie aussi le luxe de concevoir leurs interface avec brio. C&#8217;est ce qu&#8217;on pourrait <a href="http://www.fredcavazza.net/2008/01/10/connaissez-vous-la-simplexite/">simplexité</a> : une <strong>interface simple qui se complexifie sur demande</strong> en fonction des besoins.<br />
Vous vous souvenez également avoir cliqué sur message de confirmation pour supprimer, archiver ou déplacer des emails ? Non : à la place vous avez un message <q>Annuler</q> qui s&#8217;affiche une fois l&#8217;action effectuée. C&#8217;est le fameux <q><a href="http://www.37signals.com/svn/archives2/googles_gmail_undo.php">undo</a></q> et c&#8217;est génial car il permet de se tromper tout simplement. Avec ce procédé, l&#8217;erreur est permise puisqu&#8217;on peut revenir en arrière. Ce qui n&#8217;est pas le cas avec un <q>Êtes-vous sûr ? Oui / Non</q> &#8230;</p>
<p>Leurs interfaces ne sont pas forcément belles, ne proposent pas d&#8217;effets graphiques de furieux mais elles sont claires, lisibles et fonctionnelles. En d&#8217;autres termes elles sont <strong>ergonomiques et pratiques</strong>.</p>
<p>Une raison de plus d&#8217;utiliser des services Google.</p>
<h4>La gratuité n&#8217;a pas de prix</h4>
<p>Pourquoi payer quand on peut avoir quelque chose gratuitement ? Cet adage habille très bien Google puisque tous les services grand public sont gratuits (avec éventuellement quelques options payantes). Je me souviens encore des railleries au lancement de Gmail : <q>1Go pour ses mails ? Ça sert à rien</q>.<br />
Il n&#8217;empêche que pour bénéficier d&#8217;une telle capacité à l&#8217;époque il fallait mettre la main à la poche. Et effectuer une <strong>recherche pour trouver un email datant de 3 ans ça n&#8217;a pas de prix</strong> &#8230; ou plutôt si ça en un : c&#8217;est cher, très cher. Mais pas pour Google. Maintenant qui cracherait sur son archivage d&#8217;emails ?</p>
<p>Cette gratuité n&#8217;est pas de la philanthropie de la part de Google (la <a href="http://www.google.org/">Fondation Google</a> est là pour ça). Tout ceci repose quasiment exclusivement sur la publicité. Plus Google affiche de publicités et plus Google gagne de l&#8217;argent.<br />
<a href="http://www.google.com/adsense">Google Adsense</a> est un véritable cheval de Troie puisque la régie publicitaire va jusqu&#8217;à s&#8217;imposer sur la majorité des sites du monde entier et &#8230; rapporte de l&#8217;argent à ses utilisateurs.</p>
<p>En clair, <strong>utiliser Google est gratuit mais permet même de générer des revenus</strong>. Elle est pas belle la vie ?</p>
<h4>Une innovation qui hisse le Web</h4>
<p>Une autre raison de soutenir Google et/ou d&#8217;utiliser ses services est en rapport avec la <strong>dynamique que le géant a su insuffler au Web</strong> : l&#8217;innovation. Le grand réveil est apparu avec l&#8217;introduction de <em>Gmail</em> et par la suite, de <em>Google Maps</em>. Ces 2 services ont été le catalyseur de ce qui a été bêtement appelé &laquo;&nbsp;Web 2.0&#8243;. Le Web était tout simplement passé de l&#8217;enfance à l&#8217;adolescence.</p>
<p>Par delà cet aspect visible, il y a également un travail de l&#8217;ombre avec des contributions à des projets libres tels que <a href="http://www.getfirefox.com/">Mozilla Firefox</a>, <a href="http://www.winehq.org/">Wine</a> ou encore <a href="http://www.mysql.com/">MySQL</a>. Google utilise ces produits et redistribue ses contributions par rapport à son utilisation.<br />
En fournissant une forge nommée <a href="http://code.google.com/">Google Code</a>, Google permet aussi à des projets de naître en leur fournissant une infrastructure, certes limitée, à moindre coût.</p>
<h3>De quoi est-on en droit de se méfier ?</h3>
<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2008/03/google-dont-be-evil.gif' alt='Google : Don’t Be Evil' /></p>
<h4>Don&#8217;t be evil</h4>
<p>Tout ceci paraît bien évidemment idylique : Google est beau, Google est grand, Google est fort. Son slogan est même <q>Don&#8217;t be Evil</q>. Ne sois pas mauvais. <strong>Sauf que mauvais, Google l&#8217;est quelques fois</strong>. Notoriété oblige, tout problème est amplifié, à tort ou à raison et se termine parfois en polémique obligeant Google à faire marche arrière.</p>
<p>Des exemples ? La <a href="http://arstechnica.com/news.ars/post/20071226-christmas-of-controversy-for-google-reader-team.html">controverse Google Reader et des amis</a>, le <a href="http://www.zorgloob.com/2007/04/google-et-lafp-trouvent-un-terrain.asp">scandale AFP/Google News</a>, l&#8217;<a href="http://www.webpronews.com/topnews/2005/11/01/google-print-continues-amid-controversy">indexation des livres avec Google Books</a> (anciennement Google Print), la sortie de <a href="http://37signals.com/svn/archives2/google_web_accelerator_hey_not_so_fast_an_alert_for_web_app_designers.php">Google Web Accelerator</a>, <a href="http://www.readwriteweb.com/archives/google_sites_the_next_sharepoint_maybe_notwhy_google_apps_could_lose_the_enterprise_market.php">les clauses abusives de Google Sites</a> ou encore les <a href="http://www.readwriteweb.com/archives/your_email_password_a_true_hor.php">failles Gmail sources de fraudes</a> (n&#8217;utilisez <em>jamais</em> ces formulaires demandent login et mot de passe par pitié).</p>
<p>On ne peut pas dire que la communication de Google à ce niveau aie été exemplaire ni &#8230; entendue.</p>
<h4>Une communication destructurée</h4>
<p>En y réfléchissant, <strong>qui sait ce que Google va lancer dans 1, 2, 3 ou 6 mois</strong> ? Pas grand monde. Si on sait que le <a href="http://googlesystem.blogspot.com/2006/08/googles-master-plan.html">Master Plan</a> est la clé de tout, toujours est-il qu&#8217;on ne sait pas et qu&#8217;en dehors des annonces de produit, Google cultive le mystère.</p>
<p>Cette stratégie a beau limiter au maximum les plagiats de la concurrence mais ça limite également grandement la visibilité sur les objectifs de Google. Aux questions <q>Quand est-ce qu&#8217;un service sera amélioré ?</q>, <q>Quel service a été arrêté ?</q> ou encore <q>La faille a-t-elle été corrigée</q>, vous apprendrez bien souvent les réponses à vos dépends.</p>
<p>Cette communication du <em>blackout</em> est problématique pour une société censée &#8230; agréger et traiter l&#8217;information. Je pense qu&#8217;un peu de <strong>transparence et une meilleure organisation de l&#8217;information</strong> interne à Google lui éviterait quelques déboires et des inquiétudes de la part d&#8217;utilisateurs.</p>
<p style="text-align:center"><img src='http://case.oncle-tom.net/images/2008/03/google-web-accelerator.gif' alt='Google Web Accelerator stats' /></p>
<h4>À la merci d&#8217;une politique obscure</h4>
<p>Quand on aime, on ne compte pas. Et on se retrouve avec une majorité de produits Google dans notre quotidien.<br />
Ces produits sont nombreux, variés et certains sont totalement inconnus. C&#8217;est comme ça que <a href="http://googleblog.blogspot.com/2006/11/adieu-to-google-answers.html">certains produits ferment du jour au lendemain</a> sans qu&#8217;on sache trop pourquoi si ce n&#8217;est qu&#8217;ils sont peu utilisés.</p>
<p><strong>Attention à ne pas prendre de raccourci</strong> : quand on lance beaucoup de services il est normal que certains meurent. Pourtant à côté de ça certains subsistent alors qu&#8217;ils sont pestiférés (<em>Google Directory</em> ou <em>Google Web Accelerator</em>). On ne sait jamais QUAND ça va arriver, on ne sera jamais prévenu AVANT. Difficile de baser un produit dessus ou d&#8217;en faire une fonctionnalité sur son propre site avec une telle politique.<br />
Votre épicier vous prévient avant de partir en congès alors pourquoi pas Google ?</p>
<p>Le pire c&#8217;est peut-être quand on n&#8217;utilise pas Google mais une société que Google rachète : les clients d&#8217;<a href="http://fr.wikipedia.org/wiki/Urchin_Software_Corporation">Urchin</a> et de GrandCentral se mordent encore les doigts de ces acquisitions. À peine rachetés, ces services ont été fermés/non-maintenus. Il aura fallu attendre 3 ans pour qu&#8217;une nouvelle version du logiciel Urchin sorte &#8230; en beta. C&#8217;est d&#8217;autant plus problématique que c&#8217;était le logiciel de sa catégorie le plus abouti.</p>
<h3>Conclusion</h3>
<p>Je ne fais pas partie de ceux qui adulent corps et âme Google.<br />
Je ne fais pas non plus partie de ceux qui lui crachent dessus systématiquement.</p>
<p><strong>Je suis un utilisateur de Google qui apprécie ses produits pour ce qu&#8217;ils sont</strong>, pour leur utilité et leur conception. À juste titre je me sens concerné par l&#8217;attitude de la société. Parler à des millions d&#8217;utilisateurs n&#8217;a rien de facile je le concède largement mais un développeur travaillant avec des outils Google, une société travaillant avec des outils Google ou même un utilisateur employant avec des outils Google ne devrait craindre la fermeture d&#8217;un service et la perte des données qui s&#8217;ensuit.<br />
Google applique des principes d&#8217;ergonomie astucieux sur ses interfaces. <strong>Cela devrait être la même chose avec ses clients</strong>. Une trop grosse partie du Web repose sur Google pour que celui-ci ne se permette de devenir <em>evil</em>, ne serait-ce qu&#8217;un peu.</p>
<p>À l&#8217;heure actuelle la bulle Google a perdu de sa stature avec une action malmenée en Bourse, des services qui évoluent peu/pas et un attentisme important vis à vis d&#8217;<a href="http://code.google.com/android/">Android</a> (système d&#8217;exploitation sur téléphone mobile) et d&#8217;<a href="http://code.google.com/apis/opensocial/">OpenSocial</a> (réutilisation des données entre sites pour éviter de vous recréer sempiternellement vos listes d&#8217;amis, entre autre). Ce dernier a été annoncé au moment où Facebook volait la vedette au journal de 20H. Qu&#8217;en est-il maintenant que la starification est retombée ?</p>
<p><strong>Il est important d&#8217;avoir un regard critique</strong> sur les services employés et sur les méthodes pratiquées. Être fan d&#8217;un produit est aujourd&#8217;hui dangereux si c&#8217;est pour être enfermé par celui-ci. On en paie aujourd&#8217;hui les conséquences avec Internet Explorer, par exemple, devenu un véritable fardeau pour Microsoft dans sa version 6. Tout le Web aimerait s&#8217;en débarasser. Mais beaucoup se sont basés dessus et exclusivement dessus.<br />
<strong>L&#8217;Histoire peut très bien se répéter</strong> avec une situation monopolistique de Mac qui a la fâcheuse habitude d&#8217;enfermer ses utilisateurs en verrouillant et protégeant à n&#8217;en plus finir.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/google-ange-demon-vie-numerique/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>MySQL : tris personnalisés et aléatoires</title>
		<link>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/</link>
		<comments>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 11:00:12 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[order by]]></category>
		<category><![CDATA[tris]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/08/21/mysql-tri-personnalises-aleatoires/</guid>
		<description><![CDATA[La majorité des systèmes de bases de données permettent de trier une sélection de données en fonction de nos besoins, souvent de manière simple. La majorité des besoins courants impliquent des tris ascendants ou descendants (comprendre &#171;&#160;par ordre alphabétique croissant ou descendant&#160;&#187;) sur une plusieurs colonnes (des dates, des titres ou des codes particuliers) mais [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/08/powered-by-mysql-167x86.png" alt="Logo MySQL" /></p>
<p>La majorité des systèmes de bases de données permettent de trier une sélection de données en fonction de nos besoins, souvent de manière simple. La majorité des besoins courants impliquent des tris ascendants ou descendants (comprendre &laquo;&nbsp;par ordre alphabétique croissant ou descendant&nbsp;&raquo;) sur une plusieurs colonnes (des dates, des titres ou des codes particuliers) mais de temps à autre, il arrive que les  besoins soient plus complexes puisque l&#8217;on voudra soit :</p>
<ul>
<li>un <strong>ordre aléatoire</strong></li>
<li>un <strong>ordre bien précis</strong>, ni ascendant ni descendant</li>
</ul>
<p><span id="more-743"></span></p>
<h3>Le mécanisme de tri (<code>ORDER BY</code>)</h3>
<p>Pour bien comprendre comment fonctionne en détail la commande <code>ORDER BY</code>, je vous invite à lire la documentation concernant les <a href="http://dev.mysql.com/doc/refman/5.1/en/order-by-optimization.html">optimisations relatives à ORDER BY</a>. Ce que l&#8217;on doit en retenir :</p>
<ol>
<li><strong>le tri est effectué sur les données filtrées</strong> par un éventuel <code>WHERE</code> ;</li>
<li><strong>il y a 2 algorithmes de tri</strong> : l&#8217;un utilisant <em>deux passes</em>, l&#8217;autre n&#8217;utilisant qu&#8217;<em>une passe</em> mais davantage de mémoire ;</li>
<li>l&#8217;algorithme en une passe n&#8217;est pas valable pour des tris sur des données de type <code>TEXT</code> ou <code>BLOB</code> ;</li>
<li><strong>un tri sur un index est largement plus rapide</strong> et plus performant que sur des valeurs non-indexées</li>
</ol>
<p>Lorsqu&#8217;on veut trier des données, il vaut donc mieux <em>écrémer au mieux la plage de données</em> grâce à de judicieux filtres <code>WHERE</code> et de préférence, sur des colonnes indexées.</p>
<p>Mais revenons à nos moutons.</p>
<h3>Tri aléatoire (<code>ORDER BY RAND()</code>)</h3>
<p><strong>Deux solutions s&#8217;offrent au développeur pour effectuer un tri aléatoire</strong> : recueillir les données voulues et les trier <em>via</em> langage de programmation (<code>sort()</code>, <code>ksort()</code> etc.) ou alors trier directement à la source <em>via</em> la base de données.<br />
Si les bases de données portent leur nom, c&#8217;est bien parce qu&#8217;elles sont performantes dans leur travail donc autant leur laisser celui-là, celui du tri aléatoire, qui sera bien plus rapide et performant, surtout sur des volumes importants de données.</p>
<p>Cette solution est relativement connue, <code>ORDER BY RAND()</code> mélange les données recueillies de manière totalement aléatoire, sans tenir compte des index ni de quoi que ce soit d&#8217;autre. Pensez à utiliser une clause <code>LIMIT</code> si vous ne voulez récupérer qu&#8217;un nombre défini de lignes.</p>
<pre><code class="sql">SELECT * FROM `ma_table` ORDER BY RAND() LIMIT 1 ;</code></pre>
<p>Cette instruction prendra une ligne et une seule, au hasard. Rapide, concis et efficace.</p>
<h3>Tri personnalisé (<code>ORDER BY FIELD()</code>)</h3>
<p>Pire que le tri aléatoire, il y a celui du tri personnalisé, celui qui n&#8217;est <em>ni</em> ascendant, <em>ni</em> descendant, <em>ni</em> aléatoire : on veut un ordre précis. Imaginons que nous nous trouvions avec la table  suivante :</p>
<table class="code sql" border="0">
<thead>
<tr>
<th>jour_id</th>
<th>jour_nom</th>
</tr>
</thead>
<tbody>
<tr>
<th>ven</th>
<td>Vendredi</td>
</tr>
<tr>
<th>lun</th>
<td>Lundi</td>
</tr>
<tr>
<th>dim</th>
<td>Dimanche</td>
</tr>
<tr>
<th>mer</th>
<td>Mercredi</td>
</tr>
<tr>
<th>sam</th>
<td>Samedi</td>
</tr>
<tr>
<th>jeu</th>
<td>Jeudi</td>
</tr>
<tr>
<th>mar</th>
<td>Mardi</td>
</tr>
</tbody>
</table>
<p>Comment faire pour récupérer la liste des jours de semaine dans l&#8217;ordre de notre choix ? Tout simplement en utilisant la <a href="http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_field">fonction FIELD()</a> (depuis MySQL 4) :</p>
<pre><code class="sql">SELECT jour_nom
FROM `dates_semaine`
ORDER BY FIELD( <em>jour_id</em>, 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim' ) ;</code></pre>
<p>J&#8217;aurais tendance à dire que la requête parle d&#8217;elle-même : on spécifie un tri sur le champ <em>jour_id</em> dans l&#8217;ordre passé dans les paramètres suivants.<br />
Ce qui est intéressant dans notre cas c&#8217;est qu&#8217;on peut donc gérer des semaines débutant le jeudi, le samedi, le dimanche ou le lundi (histoire de coller avec tous les calendriers existants). Seuls les paramètres à donner à la requête changeraient.<br />
C&#8217;est également intéressant pour <strong>trier le résultat d&#8217;une requête en fonction de l&#8217;ordre des lignes d&#8217;un fichier</strong> qui aurait été uploadé sur un serveur.</p>
<h3>Conclusion</h3>
<p>La clause <code>ORDER BY</code> est plus puissante qu&#8217;il n&#8217;y paraît. <strong>Elle est garante de l&#8217;ordre des résultats retournés</strong>. Si dans certains cas l&#8217;ordre n&#8217;a pas d&#8217;importance, le contraire peut également être valable. Et c&#8217;est précisément dans ce cas que l&#8217;on aime à pouvoir manipuler les données comme on l&#8217;entend.<br />
Il existe d&#8217;autres possibilités intéressantes en combinant par exemple le tri et les recherches <em>FULLTEXT</em> pour <strong>récupérer les lignes par ordre de pertinence</strong> ou pourquoi pas sur des <strong>résultats de calcul</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/mysql-tri-personnalises-aleatoires/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Utilisation de variables dans MySQL</title>
		<link>http://case.oncle-tom.net/2007/utilisation-variables-mysql/</link>
		<comments>http://case.oncle-tom.net/2007/utilisation-variables-mysql/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 11:00:30 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/07/13/utilisation-variables-mysql/</guid>
		<description><![CDATA[MySQL, depuis la version 3.23.6, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire. Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;API d&#8217;autres langages (PHP, Perl, C# etc.). Et pourtant ça peut vous être très utile pour économiser [...]]]></description>
			<content:encoded><![CDATA[<p><strong>MySQL</strong>, depuis la version <em>3.23.6</em>, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire.</p>
<p>Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;<acronym title="Application Programming Interface"><acronym title="Application Programming Interface">API</acronym></acronym> d&#8217;autres langages (<acronym title="PHP : Hypertext Processor"><acronym title="Pre-Hypertext Processing">PHP</acronym></acronym>, <acronym title="Practical Extraction and Report Language">Perl</acronym>, C# etc.). Et pourtant ça peut vous être très utile pour économiser des requêtes, du temps à programmer ces boucles et puis surtout, <strong>par flemme</strong>.</p>
<p>Oui, la flemme est pour moi la <strong>qualité numéro un</strong> du développeur car <em>le flemmard a pour but d&#8217;arriver à ses fins en un minimum d&#8217;efforts</em>.<br />
<span id="more-618"></span></p>
<h3>Déclaration de variables</h3>
<p>On peut déclarer une variable de deux façons dans MySQL.<br />
La première méthode consiste à utiliser l&#8217;opérateur <code>SET</code>.</p>
<pre><code class="sql">SET @pierre = 3, @feuille = 3 + 2, @ciseau = @pierre % @feuille ;</code></pre>
<p>On peut également consister une variable à partir d&#8217;une requête.</p>
<pre><code class="sql">SELECT @nb_total := COUNT(*) FROM `ma_table` ;</code></pre>
<p><strong>Note</strong> : dans ce cas là, on préfixe l&#8217;opérateur <code>=</code> de <code>:</code> (deux points).</p>
<h3>Utilisation simple des variables</h3>
<p>L&#8217;utilisation première qui peut en être faite c&#8217;est d&#8217;assainir vos requêtes <acronym title="Structured Query Language">SQL</acronym> en évitant au maximum l&#8217;apparition de variables issues d&#8217;autres langages.<br />
<strong>Avant</strong> :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE colonne1 = {$variable1}, colonne2 = '{$variable2}' LIMIT 1;</code></pre>
<p><strong>Après</strong> :</p>
<pre><code class="sql">SET @variable1 = {$variable1}, @variable2 = '{$variable2}';
SELECT * FROM `ma_table` WHERE colonne1 = @variable1, colonne2 = @variable2 LIMIT 1;</code></pre>
<p>Comme les variables sont effectives pour la connexion courante, une variable MySQL peut être réutilisée à tout moment. De quoi décomplexifier certains scripts pas forcément bien structurés.</p>
<h3>Utilisation complexe des variables</h3>
<p><strong>Les variables peuvent également être modifiées à même la requête</strong>. C&#8217;est à dire qu&#8217;à chaque itération effectuée par MySQL, le moteur va réévaluer le contenu de la variable. J&#8217;ai notamment eu besoin de ça pour ajouter de nouveaux éléments à la suite d&#8217;autres tout en renumérotant leur ordre. Je souhaitais <strong>éviter une boucle récursive en <acronym title="Pre-Hypertext Processing">PHP</acronym></strong> qui aurait occasionné de multiples requêtes.</p>
<p>Je dispose d&#8217;une table (<code>item_liste</code>) avec plusieurs éléments, une clé primaire sur deux champs (<code>item_id</code> et <code>item_cat</code>) ainsi qu&#8217;un autre champ indexé permettant de les trier dans un ordre donné (<code>item_ordre</code>). Le but : prendre des éléments de la catégorie 1 pour les mettre à la suite de la catégorie 2.</p>
<p>Voici en gros ce que ça donne au final :</p>
<pre><code class="sql">SELECT @ordre := IFNULL(MAX(item_ordre), 0) FROM `item_liste` WHERE item_cat = 2 ;
UPDATE `item_liste` SET item_ordre = @ordre := @ordre+1, item_cat = 2 WHERE item_cat = 1 ;</code></pre>
<ol>
<li>On compte la borne supérieure de la catégorie 2. Pourquoi un <code>IFNULL</code> ? Parce <code>MAX()</code> retournera <code>NULL</code> si un des <code>item_ordre</code> en contient un. C&#8217;est une sécurité ;</li>
<li>On met à jour les éléments de la catégorie 1 avec leur nouvel ordonnancement et leur nouvelle catégorie.</li>
</ol>
<p><strong>Alors pourquoi ça fonctionne</strong> ? La commande <code>UPDATE</code> balaie les lignes <strong>une par une</strong> et du coup, <strong>met à jour la variable <code>@ordre</code> à chaque ligne</strong>. Nous retrouvons ainsi l&#8217;effet désiré : incrémenter chaque ligne déplacée dans la nouvelle catégorie.</p>
<p>Il existe des utilisations plus compliquées que celles-là mais je pense que c&#8217;est un bon départ pour se faire une idée de ce qui est faisable par ce biais là. L&#8217;imagination et les besoins feront le reste <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/utilisation-variables-mysql/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Livres : Javascript, Subversion, CSS</title>
		<link>http://case.oncle-tom.net/2007/livres-javascript-subversion-css/</link>
		<comments>http://case.oncle-tom.net/2007/livres-javascript-subversion-css/#comments</comments>
		<pubDate>Tue, 24 Apr 2007 11:00:53 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[livres]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[svn]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/04/24/livres-javascript-subversion-css/</guid>
		<description><![CDATA[Je vous l&#8217;annonce, depuis janvier 2007 je suis boulimique. Boulimique mais d&#8217;informations, de connaissances et de savoir. S&#8217;il y a bien un univers qui ne pardonne pas à ceux qui se contentent des acquis, c&#8217;est bien celui d&#8217;Internet. Donc en plus des 300 brèves quotidiennes que je lis, je viens de passer commande de trois [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img id="image578" src="http://case.oncle-tom.net/images/2007/04/ppk-javascript-css-mastery-subversion.png" alt="Ppk on Javascript / CSS Mastery / Subversion" /></p>
<p>Je vous l&#8217;annonce, depuis janvier 2007 <em>je suis boulimique</em>. Boulimique mais d&#8217;informations, de connaissances et de savoir. S&#8217;il y a bien un univers qui ne pardonne pas à ceux qui se contentent des acquis, c&#8217;est bien celui d&#8217;Internet. Donc en plus des 300 brèves quotidiennes que je lis, je viens de passer commande de trois livres :</p>
<ul>
<li><a href="http://www.quirksmode.org/book/">Ppk on Javascript</a> (<em>New Riders Publishing</em>, en anglais)</li>
<li><a href="http://www.cssmastery.com/"><acronym title="Cascading Style Sheets">CSS</acronym> Mastery</a> (<em>Friends of ED</em>, en anglais)</li>
<li><a href="http://www.editions-eyrolles.com/Livre/9782212119190/subversion">Subversion : Pratique des projets collaboratifs avec <acronym title="Subversion">SVN</acronym></a> (<em>Eyrolles</em>, en français)</li>
</ul>
<p><span id="more-579"></span><br />
Au début de l&#8217;année j&#8217;avais jeté mon dévolu sur trois autres références pour voir où j&#8217;en étais, ce que j&#8217;avais encore à apprendre (beaucoup) et ce qui pouvait me faciliter la vie :</p>
<ul>
<li><strong><acronym title="Pre-Hypertext Processing">PHP</acronym> 5 avancé</strong> (<em>Eyrolles</em>) que j&#8217;avais trouvé moyen car davantage débutant qu&#8217;avancé</li>
<li><strong>Maîtriser MySQL 5</strong> (<em>O&#8217;Reilly</em>) que je n&#8217;ai pas encore terminé mais intéressant bien que pas assez complet à mon goût au niveau des fonctions utiles</li>
<li><strong>Gestion de projets avec Subversion</strong> (<em>O&#8217;Reilly</em>) que je n&#8217;ai pas non plus terminé, très technique et instructif mais il me manquait les bases pour bien comprendre <em>comment bien utiliser Subversion</em></li>
</ul>
<p>D&#8217;ailleurs peut-être que ça en intéresse certains d&#8217;avoir une critique de plus sur ces ouvrages. Faites signe (ou canard) <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>C&#8217;est finalement en relisant un article fort intéressant concernant <a href="http://www.biologeek.com/journal/index.php/installer-un-depot-subversion-sous-ubuntu">l&#8217;installation d&#8217;un dépôt Subversion sous Ubuntu</a> que j&#8217;ai décidé de passer à l&#8217;acte.</p>
<h3>Subversion : Pratique des projets collaboratifs avec <acronym title="Subversion">SVN</acronym></h3>
<p><strong>Subversion</strong> est un formidable outil de gestion et d&#8217;archivage de fichiers très utilisé dans les projets informatiques. Il est performant, efficace et permet le travail simultané de plusieurs personnes sur un même projet. Je souhaitais coupler cet outil avec l&#8217;<strong>interface en ligne TRAC</strong> pour gérer des tickets d&#8217;incidents ainsi que les feuilles de route. <em>Pour ne plus jamais oublier un bug à corriger ou une fonctionnalité à rajouter</em>.</p>
<h3>Ppk on Javascript</h3>
<p>J&#8217;ai découvert le site de l&#8217;auteur bien avant qu&#8217;il écrive son livre et je le trouvais déjà fort bien renseigné concernant les différences de comportement entre les différents navigateurs Web concernant Javascript. Egalement de bonnes explications à propos de la gestion des objets, des évènements et les manipulations du <acronym title="Document Object Model">DOM</acronym>. Ce livre très orienté sur la pratique et l&#8217;expérience de son auteur (le plus important à mes yeux) aborde les manipulations de <acronym title="Cascading Style Sheets">CSS</acronym>, les incompatibilités des navigateurs, bien déboguer son code ainsi que des cas pratiques avec des exemples concrets. Pour que <code>Thomas = { 'taille' : 183, 'feignant' : true }</code> ne soit plus un mystère pour vous <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3><acronym title="Cascading Style Sheets">CSS</acronym> Mastery</h3>
<p>La même chose que <em>Ppk on Javascript</em> mais avec des <acronym title="Cascading Style Sheets">CSS</acronym> ! Pour bien comprendre les différents bugs des navigateurs, les histoires de DOCTYPE et de mode navigateur, les bonnes pratiques pour maintenir son code <acronym title="Cascading Style Sheets">CSS</acronym>, les hacks, les filtres et tout ce qui est recommandé ou pas. Bref ça me paraît être un bon choix.</p>
<p>Rendez-vous dans quelques temps : on verra bien si ça me servira <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/livres-javascript-subversion-css/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IN() et GROUP_CONCAT() sont dans un bateau</title>
		<link>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/</link>
		<comments>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/#comments</comments>
		<pubDate>Mon, 09 Apr 2007 11:00:31 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/04/09/in-et-group_concat-sont-dans-un-bateau/</guid>
		<description><![CDATA[Il m&#8217;arrive fréquemment d&#8217;avoir à sélectionner des lignes de données à partir d&#8217;un ou plusieurs critères. C&#8217;est le cas dès que l&#8217;on souhaite récupérer une liste. C&#8217;est également très pratique pour mettre à jour ces dites-lignes. Seulement voilà, des fois on pourrait éviter quelques boucles et quelques complications avec l&#8217;utilisation de deux fonctions magiques de [...]]]></description>
			<content:encoded><![CDATA[<p>Il m&#8217;arrive fréquemment d&#8217;avoir à sélectionner des lignes de données à partir d&#8217;un ou plusieurs critères. C&#8217;est le cas dès que l&#8217;on souhaite récupérer une liste. C&#8217;est également très pratique pour mettre à jour ces dites-lignes. Seulement voilà, des fois on pourrait éviter quelques boucles et quelques complications avec l&#8217;utilisation de deux fonctions magiques de MySQL : <a href="http://dev.mysql.com/doc/refman/4.1/en/comparison-operators.html">IN()</a> et <a href="http://dev.mysql.com/doc/refman/4.1/en/group-by-functions.html">GROUP_CONCAT()</a>.<br />
<span id="more-550"></span></p>
<h3>Sélection optimisée avec IN()</h3>
<p><code>IN()</code> devrait être utilisé dès lors que l&#8217;on a plusieurs critères sur un même colonne. L&#8217;écriture suivante ne devrait pas apparaitre dans votre code :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE id = 3 OR id = 5;</code></pre>
<p>A la place, il devrait y avoir ceci :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE id IN (3, 5);</code></pre>
<p>C&#8217;est une habitude à prendre car elle permettra d&#8217;automatiser bien des choses. Imaginez qu&#8217;on ne fasse plus cette sélection &laquo;&nbsp;en dur&nbsp;&raquo; mais à partir d&#8217;un tableau <acronym title="Pre-Hypertext Processing">PHP</acronym>. Trois façons d&#8217;écrire la requête, vous verrez vite laquelle sera la plus pratique à réutiliser :</p>
<pre><code class="php">
$tableau = array(3, 5);
/* Méthode 1 : vite-fait mal fait */
$separateur = '';
$sql = "SELECT * FROM `ma_table` WHERE ";
foreach( $tableau as $id )
{
	$sql .= $separateur." id = ".$id;
	$separateur = ' OR ';
}
/* Méthode 2 : utilisation "optimisée" avec des OR dans la requête */
$sql = "SELECT * FROM `ma_table` WHERE id = ".implode(' OR id = ', $tableau);
/* Méthode 3 : passe-partout */
$sql = "SELECT * FROM `ma_table` WHERE id IN (".implode(',', $tableau).")";
</code></pre>
<p>Le gros avantage de la dernière méthode c&#8217;est le retraitement des données. Il est facile et plus logique d&#8217;<a href="http://fr.php.net/implode">imploser</a> et d&#8217;<a href="http://fr.php.net/manual/fr/function.explode.php">exploser</a> une chaine composée de <em>séparateurs virgule</em> (ou autre caractère employé aux mêmes fins).</p>
<pre><code class="php">$tableau = array(3, 5);
$tableau = implode(',', $tableau);
/* du code nécessitant $tableau en tant que chaîne */
$tableau = explode(',', $tableau);
/* du code nécessitant $tableau en tant que tableau */</code></pre>
<h3>Aggrégats avec GROUP_CONCAT()</h3>
<p>Dans les exemples précédents, <code>$tableau</code> était rempli &laquo;&nbsp;en dur&nbsp;&raquo;. Dans la vraie vie, ça ne se passe pas comme ça : on récupère des identifiants (clés et/ou index) pour valider les sélections. L&#8217;exemple basique : <em>on veut mettre à jour une table de configuration avec les ID d&#8217;articles présents dans une ou plusieurs catégories</em>.</p>
<pre><code class="php">$tableau = array();
/* Sélection des ID */
$query = mysql_query("SELECT id FROM `ma_table` WHERE cat_id IN ('fromage', 'tortues');");
while( $ligne = mysql_fetch_assoc($query) )
{
	$tableau[] = $ligne['id'];
}
/* On met à jour notre table de configuration */
$tableau = implode(',', $tableau);
mysql_query("REPLACE INTO `table_config` (config_id, config_valeur) ".
	"('cache_articles', '{$tableau}')");</code></pre>
<p>C&#8217;est simple, propre et on se dit qu&#8217;on a bien bossé. Et pourtant, l&#8217;utilisation de la fonction d&#8217;agrégation <code>GROUP_CONCAT()</code> de MySQL nous épargnera quelques lignes. On appréciera :</p>
<pre><code class="php">$tableau = array();
/* Sélection des ID */
$query = mysql_query("SELECT GROUP_CONCAT(id) AS cache_articles FROM `ma_table` WHERE cat_id IN ('fromage', 'tortues');");
$tableau = mysql_fetch_assoc($query);
/* On met à jour notre table de configuration */
mysql_query("REPLACE INTO `table_config` (config_id, config_valeur) ".
	"('cache_articles', '{$tableau['cache_articles']}'");</code></pre>
<p>Bref, on a gagné une boucle (le <code>while</code>), des lignes de résultats MySQL (autant de ressources d&#8217;économisées) et un traitement <acronym title="Pre-Hypertext Processing">PHP</acronym> en moins (<code>implode</code>). Et devinez quoi ? Le résultat retourné par le <code>GROUP_CONCAT</code> s&#8217;intègre très bien dans le &#8230; <code>IN()</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/in-et-group_concat-sont-dans-un-bateau/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

