26
Jan/10
1

L’importance des clés primaires avec mk-table-sync

J’adore Maatkit. Je m’en sers régulièrement dans toutes sortes d’occasions. Pour tous les Slaves que je configure, j’ajoute un petit script maison qui utilise mk-table-sync afin valider l’intégrité des données sur le Slave avec le Master. Ce petit script envoie un email avec les différences et les requêtes à exécuter le cas échéant.

J’ai remarqué que mk-table-sync possède certaines limitations, c’est-à-dire que le format de la table et l’encoding joue un rôle important sur la manière dont l’outil effectue ses comparaisons. Les tables sans clé primaire ou d’identifiant unique sont particulièrement problématiques, et c’est tout à fait compréhensible. Par définition, s’il n’y a pas d’identifiant unique, il est impossible d’être 100% sur que l’enregistrement #1 sur le Master correspond à l’enregistrement #1 sur le Slave. En étant limité à ce niveau, mk-table-sync  préfère “croire” que l’ensemble des données sur le Slave sont erronés et propose des requêtes pour supprimer et réinsérer tous les enregistrements de la table.

Bien que je m’assure que toutes les tables possèdent des clés primaires lors de leur création, il m’est arrivé de me faire avoir. Le statement CREATE TABLE tableName SELECT * FROM tableName2 WHERE …. ; crée une table SANS index! Du coup, mon petit script s’est mis à envoyer des emails de 17Mo de requêtes SQL, ce que Thunderbird digère très mal ;)

La leçon est: si vous utilisez mk-table-sync, assurez-vous de TOUJOURS avoir un identifiant unique sur vos tables!

3
Dec/09
0

Retrospective du Demo Camp de Montréal

Comme plusieurs bons ScrumMasters, j’applique des principes de scrums dans ma vie quotidienne. Dans ce sens, je me permets de publier ma rétrospective du Demo Camp d’hier soir.

Dans les points négatifs à améliorer:

  • Ne pas essayer de faire une présentation de 30 minutes en 10 minutes
  • S’informer davantage sur la formule de présentation
  • Prévoir que le Xorg de mon debian n’allait pas supporter les résolutions des mégas projecteurs
  • Prévoir que simuler le crash d’une DB et la recouvrir live implique un certain nombre de risques
  • Pratiquer la présentation, plus, beaucoup plus

Dans les points positifs à retenir:

  • De la bière gratuite fournie par Microsoft
  • Élargis mon réseau de contacts

J’ai spécialement aimé la présentation de DokDok.

Comme promis, je publie le script de backup que j’ai finalement à peine présenté. Anyway, pour les intéressés, il se trouve ici.

Tagged as:
30
Nov/09
2

MySQL Sandbox: bravo !

J’ai souvent entendu parler de MySQL Sandbox. Pour effectuer des tests avec un Master/Slave en fin de semaine, j’ai décidé de l’essayer puisque je n’avais que mon laptop. MySQL Sandbox est un outil pour installer un ou plusieurs serveurs isolés, sans affecter les autres.

Wow! Juste Wow! MySQL Sandbox est un outil vraiment génial! J’ai pu créer une instance de MySQL Master avec 2 instances Slaves sur la même machine en moins de 1 minute! C’est le genre de tâche qui prend de 30 minutes à 1 heure lorsqu’un administrateur expérimenté le fait manuellement. MySQL Sandbox permet non seulement d’installer rapidement 1 ou plusieurs serveurs, il permet aussi d’installer des versions différentes en quelque instant !

De plus, des options prédéfinies permettent de créer un setup Master-Slave ou  Master-Master automatiquement. Il vient avec des outils permettant d’effectuer des tâches d’administration complexes de manière excessivement simple. En résumé, il permet carrément de jouer avec MySQL.

Comment ça marche? On télécharge la version de MySQL qu’on souhaite installer. Ensuite, on peut

Créer une instance de MySQL:

make_sandbox  /path/to/mysql-X.X.XX-osinfo.tar.gz

Créer un Master avec 2 Slaves:

make_replication_sandbox /path/to/mysql-X.X.XX-osinfo.tar.gz

Créer 4 serveurs avec une réplication circulaire (Master-Master)

make_replication_sandbox –circular=4 /path/to/mysql-X.X.XX-osinfo.tar.gz

Ces 3 commandes installent, configurent et démarrent le ou les serveurs MySQL. En quelques mots, MySQL Sandbox c’est simplicité, rapidité et fun!
2009-11-30 00:16:29

8
Mar/09
2

Les ORM de PHP

Je n”ai pas beaucoup eu le temps d’écrire ce dernier mois. J’ai eu un mois de février plutôt chargé. Je prends le temps aujourd’hui de vous partager la petite étude que j’ai réalisée à propos des ORM PHP.

Plusieurs développeurs utilisent des ORM (Object Relational Mapping) pour faciliter et accélérer le développement d’application. Grossièrement, un ORM est un framework de communication avec une ou des bases de données. Certains ORM vont jusqu’à offrir un contrôle total de vos bases de données sans avoir à écrire une seule requête SQL. Dans le cadre d’un nouveau projet, j’ai eu à analyser les différents ORM disponibles en PHP. Voici ce que j’ai trouvé

Zend DB Doctrine Propel
Outil de unit tests non oui non
Gestion des contraintes Oui Super oui
Load Balancing des requetes (Master-Slave) non oui non
Lazy Load Oui oui non
Format des Shemas PHP ou Dynamic YAML converti en php XML
Controle des Transactions Oui oui non
Caching non Super non
Connection persistante non ? non
Profiler Oui oui non- mais log error
Langage “xQL” Oui oui Oui – mauvais
Raw SQL Oui oui oui
Stored Proc. Et Prepared Statement Oui oui oui
Querying for a set of Rows Oui oui oui
Costumizable Insert / update / delete Oui oui Probablement ?
Documentation bonne bonne Faible
Facilite d’intallation bonne moyenne* bonne
Facilite d’utilisation bonne moyenne* bonne
Outil de Migration non oui non
Outil de Performance non oui non
Validation de données selon le schema non oui super

* L’utilisation et l’installation de Doctrine ont été jugées “moyenne” du à l’ensemble des différents features disponibles. Il est de base très simple et facile, mais devient plus complexe que les autres ORM si on utilise certains features. Je suppose qu’après l’avoir utilisé durant quelques jours, on arrive à comprendre toutes les subtilités.

Vous comprenez que Doctrine semble actuellement le plus complet d’entre tous. La version stable de Propel est la 1.2; c’est la version étudiée. Par contre, la version 1.3 est très prometteuse et peut se comparer davantage à Zend DB et Doctrine.

Je n’ai pas eu l’occasion de véritablement travailler avec aucun des 3 à l’étude. Si vous utilisez ou avez utilisé un des ORM à l’étude, je vous invite à partager votre opinion sur leurs points forts ou faibles!

Tagged as: ,
18
Jan/09
1

General Log sur demande

Dans les nouveautés de MySQL 5.1, il y a l’activation / désactivation des logs sur demande. J’adore ce feature. Pour moi, c’est un outil de debug. Je m’en sers pour trouver des problèmes de performance ou de transactions qui sont souvent complexes à identifier dans une application avec une grosse architecture.

Le principe est simple: dans un environnement isolé, c’est-à-dire un environnement où vous savez que vous êtes le seul à travailler, accédez à l’interface problématique de votre application. Activez les logs avec la commande:

SET GLOBAL general_log = 1;

Lancez ensuite l’opération problématique. Lorsque terminé, désactivez de suite les logs:

SET GLOBAL general_log = 0;

Le log est maintenant rempli de toutes les requêtes effectuées durant l’opération.  C’est là que commence l’analyse. Regarder les requêtes, la quantité, l’ordre dans lequel elles sont faites, la gestion des transactions, etc.. Il n’est habituellement pas souhaitable de voir:

  • Plusieurs requêtes identiques – vous devriez songer à un système de cache
  • Plusieurs requêtes consécutives pour aller chercher une étendue d’enregistrement de la même table (ex: .. WHERE id = 1; .. WHERE id =2; .. WHERE id = 3; .. WHERE id = 4;)
  • Plusieurs connexions différentes (rappelez-vous, il s’agit d’une opération déclenchée par un seul utilisateur)
  • Plusieurs transactions simultanées.

Les logs peuvent vous démontrer plusieurs problèmes différents. J’ai découvert qu’un processus peu performant d’une application envoyait jusqu’à 5Mo de requêtes SQL. Si on estime qu’une requête SQL fait environ 100 octets, imaginez le nombre de requêtes effectuées pour se rendre à 5Mo.

Il est important de désactiver de suite les logs, car ceux-ci rendent le serveur lent et utilise abusivement de l’espace disque. De plus, l’analyse du problème peut être faussée si quelqu’un accède à votre environnement et effectue des opérations. Et surtout, n’activez JAMAIS les logs sur un serveur en production. J’ai déjà vu un log augmenter de plusieurs centaines de Mo à la minute.

Tagged as:
27
Nov/08
2

MySQL 5.1 GA

MySQL 5.1 est sorti aujourd’hui en version GA (General Availability)! Certaine personne avait avancé qu’il sortirait le 6 décembre, date que j’attendais avec impatience, mais on peut se réjouir dès maintenant !

Dans les nouveaux features de MySQL 5.1, on y retrouve (en ordre de préférence)

Il y a évidement d’autres features que ceux-la, mais ce sont mes préférés. J’ai déjà commencé à me servir de l’event scheduler dans des environnements de developpement. J’ai hate de pouvoir mettre ça en pratique dans un environnement de production!

Vous pouvez donc le télécharger ici

Filed under: Outils, Serveur
8
Oct/08
10

Je hais phpMyAdmin

Je hais phpMyAdmin. Ironiquement, je m’en sers encore beaucoup et pour me contredire davantage, je vais même avouer que c’est “relativement” un bon outil. Mais je le hais quand même.

PhpMyAdmin est l’outil qui m’a fait découvrir MySQL lorsque j’étais encore à l’école. C’est un outil idéal pour débuter en développement Web puisqu’il est intégré à des logiciels comme easyphp ou est souvent ajouté à LAMP (Linux Apache MySQL PHP). L’outil est convivial et permet de faire beaucoup d’opérations, même pour un utilisateur inexpérimenté en SQL. Plusieurs hébergeurs Web l’offrent dans leurs plans puisqu’il est gratuit, simple à installer et facile à maintenir.

Mais quand on connait bien le SQL, plus précisément MySQL, et qu’on s’en sert régulièrement comme je le fais, on en vient à constater ses lacunes. Donc, dans le top 5 des choses que je déteste de phpMyAdmin:

  1. La création des Foreign Key
    Il n’y a rien de plus simple dans phpMyAdmin que de créer une base de données et des tables. Pourtant, appliquer les concepts de clés étrangères est un exercice complexe qu’il n’est pas possible de faire à la création de la table. Une des plus grandes forces de phpMyAdmin est donc intimement liée à une de ses plus grandes faiblesses. Ce manque incite les nouveaux utilisateurs de MySQL à ne pas créer de clés étrangères.
  2. Les int(11)
    Je vois régulièrement des int(11) chez les utilisateurs de phpMyAdmin. Contrairement au char et varchar, la “longueur” des types numérique n’est pas une limite imposée. Un int(9) unsigned possède le même nombre maximal qu’un int(11). L’ironie, c’est que la longueur maximale d’un int unsigned, 4294967295, est de 10 chiffres ce qui fait de la valeur par défaut de phpMyAdmin, le int(11), un non-sens. Le seul et unique impact du nombre qu’on peut attribuer à un type numérique est lorsqu’on utilise l’attribut Zerofill. Dans ce cas, le nombre sera “padder” de 0 jusqu’à la longueur désirée. Onze (11) n’est pas une limite non plus. J’ai créé un int(100) unsigned zerofill, inséré la valeur 1, et il y avait bien 99 zéros devant mon 1 lorsque j’ai fait un SELECT. Le comportement par défaut de phpMyAdmin est trompeur.
  3. Les LIMIT 0,30
    Pour que le résultat d’une requête s’affiche rapidement, phpMyAdmin n’affiche pas la totalité des enregistrements. Il ajoute automatiquement un “LIMIT 0,30″ à chaque requête. La différence sur le temps d’exécution est remarquable, mais cette technique n’est vraiment pas pratique.
  4. Son dynamisme
    Je donne 2 sur 10 au dynamisme. J’ai eu un “vieux” phpMyAdmin designé pour MySQL 4 qui se connectait à un MySQL 5. Beaucoup de nouveaux status (show [global] status) et de nouvelles variables (show [global] variables) n’étaient pas présents dans la page qui sert à les afficher. Pourtant, si on exécute la requête manuellement les valeurs sont bien présentes. Rien de très dynamique là dedans. De plus, j’aimerais avoir accès à un “textbox” en tout temps dans le but de taper des requêtes SQL. Actuellement, je dois cliquer sur la section “SQL” qui pop une fenêtre et le résultat de celle-ci s’affiche dans une nouvelle page. Je déplore aussi le fait que je dois constamment modifier le fameux LIMIT 0,30 pour mettre une autre limit, forçant à ré-exécuter la requête et réafficher le résultat. Ce sont des choses qui pourraient aisément être évitées grâce à AJAX.
  5. Sa facilité à commettre des gaffes
    Deux cliques, c’est suffisant pour supprimer des rows, vider une table ou même une base de données entière !  Lorsqu’on tape les statements dans le CLI, nous sommes beaucoup plus alertes et conscients de ce que nous faisons. Nous perdons un peu le sens des responsabilités avec phpMyAdmin car on clique, clique et clique encore et on finit par commettre des choses irréversibles, rapidement. L’interface de gestion des privilèges est chaotique. Je préfère de loin créer les privilèges en tapant directement les statements nécessaires pour être sur de ne pas commettre d’erreur.

En résumé, phpMyAdmin demeure en bon outil malgré tout, mais ces 5 points me font rager plusieurs fois par semaine. Les outils fournir par MySQL possèdent beaucoup de faiblesses (et de bugs!). À défaut d’avoir de meilleurs outils graphiques, j’alterne entre le client en command line (le “CLI”) et phpMyAdmin.

13
Aug/08
0

Raid, Cache et BBU

Je vous parlais récemment de Sysbench, aujourd’hui je vais vous montrer comment il m’a aidé à résoudre un problème. Tout d’abord, je dois vous expliquer le problème initial. Je reçois un nouveau serveur qui sera le Master de notre environnement de pré-production, une bête dans son genre: Dual Quad Xeon 2Ghz, 32Go de RAM, 4 disques scsi montés en RAID5. Après avoir installé un backup, je lance un script qui fait des modifications massives sur les données dans le but de mesurer à quel point le nouveau serveur est performant.

Surprise ! Le script était excessivement plus lent que d’habitude. J’ai fouillé un peu et j’ai constaté que le IOwait était étrangement élevé. Après quelques recherches infructueuses sur google pour des problèmes de MySQL avec un IOwait élevé, je me suis connecté sur IRC, #MySQL (sur freenode) et j’ai parlé de ma situation. À mon grand étonnement, Clint Byrum (aka SpamapS) possèdait des réponses précises à mon problème. Nous sommes arrivé à la conclusion que la write-cache était probablement désactivée. C’était le cas.

À partir de ce constat, je décide d’utiliser Sysbench pour valider que le problème vient de la cache du RAID.

Les tests:
#1. On fait écrire dans 128 fichiers de 1MB (128MB total), les fichiers sont suffisamment petits pour que tout se fasse en cache.
#2. On fait écrire dans 128 fichiers de 8MB (1GB au total), pour être sûr de remplir la cache au complet
#3. On fait lire et écrire dans 128 fichiers de 1MB (128MB total), les fichiers sont suffisamment petits pour que tout se fasse en cache.
#4. On fait lire et écrire dans 128 fichiers de 8MB (1GB au total), pour être sûr de remplir la cache au complet

TEST #1
./sysbench –test=fileio –init-rng=1 –max-time=60 –max-requests=1000000 –file-num=128 –file-total-size=128M –num-threads=16 –file-test-mode=rndwr run

SANS LA CACHE:
Operations performed: 0 Read, 24804 Write, 31288 Other = 56092 Total
Read 0b Written 387.56Mb Total transferred 387.56Mb (6.4451Mb/sec)
412.49 Requests/sec executed

AVEC LA CACHE:
Operations performed: 0 Read, 241204 Write, 305548 Other = 546752 Total
Read 0b Written 3.6805Gb Total transferred 3.6805Gb (62.657Mb/sec)
4010.04 Requests/sec executed

—-====——–====——–====——–====——–====——–====——–====——–====——–====——–====——–====—-

TEST #2
./sysbench –test=fileio –init-rng=1 –max-time=60 –max-requests=1000000 –file-num=128 –file-total-size=1024M –num-threads=16 –file-test-mode=rndwr run

SANS LA CACHE:
Operations performed: 0 Read, 19501 Write, 24129 Other = 43630 Total
Read 0b Written 304.7Mb Total transferred 304.7Mb (5.077Mb/sec)
324.93 Requests/sec executed

AVEC LA CACHE:
Operations performed: 0 Read, 28702 Write, 35615 Other = 64317 Total
Read 0b Written 448.47Mb Total transferred 448.47Mb (7.4293Mb/sec)
475.47 Requests/sec executed

—-====——–====——–====——–====——–====——–====——–====——–====——–====——–====——–====—-

TEST #3
./sysbench –test=fileio –init-rng=1 –max-time=60 –max-requests=1000000 –file-num=128 –file-total-size=128M –num-threads=16 –file-test-mode=rndrw run

SANS LA CACHE:
Operations performed: 35345 Read, 23568 Write, 67552 Other = 126465 Total
Read 552.27Mb Written 368.25Mb Total transferred 920.52Mb (15.317Mb/sec)
980.30 Requests/sec executed

AVEC LA CACHE:
Operations performed: 70214 Read, 46809 Write, 135896 Other = 252919 Total
Read 1.0714Gb Written 731.39Mb Total transferred 1.7856Gb (30.385Mb/sec)
1944.64 Requests/sec executed

—-====——–====——–====——–====——–====——–====——–====——–====——–====——–====——–====—-

TEST #4
./sysbench –test=fileio –init-rng=1 –max-time=60 –max-requests=1000000 –file-num=128 –file-total-size=1024M –num-threads=16 –file-test-mode=rndrw run

SANS LA CACHE:
Operations performed: 16446 Read, 10964 Write, 28273 Other = 55683 Total
Read 256.97Mb Written 171.31Mb Total transferred 428.28Mb (11.971Mb/sec)
766.15 Requests/sec executed

AVEC LA CACHE:
Operations performed: 41350 Read, 27576 Write, 72158 Other = 141084 Total
Read 646.09Mb Written 430.88Mb Total transferred 1.0517Gb (17.941Mb/sec)
1148.24 Requests/sec executed

Si vous avez pris le soin d’étudier les résultats, vous avez compris que la cache apporte un gain de performance impressionnant ! On s’y attendait. L’impact sur MySQL est considérable. Cependant, il faut savoir que MySQL n’utilise qu’un seul CPU par thread, ce qui n’apporte pas un gain de performance aussi remarquable que les benchmarks lorsqu’un script utilise qu’une seule connexion.

Mon script roulait normalement après avoir activé la cache, sans être plus rapide qu’à la normal. J’étais un peu deçu, mais j’ai vite compris qu’avec plusieurs threads connectés en meme temps le serveur répondait toujours aussi rapidement. J’ai remarqué une nette amélioration lorsqu’il y a plusieurs utilisateurs connectés simultanément. Voici un petit benchmark avec la cache activé, via MySQL, avec 40 threads:

./sysbench –test=oltp –oltp-test-mode=complex –max-time=60 –max-requests=300000 –num-threads=40 –init-rng=1 –oltp-table-size=3000000 –mysql-user=testing –mysql-password=testing –mysql-host=127.0.0.1 run

queries performed:
read: 670964
write: 239630
other: 95852
total: 1006446
transactions: 47926 (798.38 per sec.)
deadlocks: 0 (0.00 per sec.)
read/write requests: 910594 (15169.31 per sec.)
other operations: 95852 (1596.77 per sec.)

Mais activer la cache n’est pas sans danger, le serveur doit posséder une batterie (BBU pour Battery Backup Unit). En cas de panne, cette batterie permet d’assurer la consistance des données sur les disques du RAID. La majorité des softwares pour activer la cache vous avertira qu’il est nécessaire d’avoir une batterie.

En résumé, si vous possédez un serveur avec du RAID, il s’avère quasiment nécessaire d’avoir une batterie et la cache d’activée pour avoir des performances à la hauteur de vos espérances.