[TSFA] 201011 MySQL Audit
Transcription
[TSFA] 201011 MySQL Audit
MySQL Rapport d'intervention OUAT ENTERTAINMENT DRAFT Copyright © 1995-2010, Oracle Corporation and/or its affiliates 1 / 38 CONFIDENTIAL MySQL® Services 1 novembre 2010 Copyright © 1995-2010, Oracle Corporation and/or its affiliates 2 / 38 CONFIDENTIAL Table des matières 1.1 Contexte .................................................................................................................................... 5 2 Informations administratives............................................................................................................. 6 2.1 Client .........................................................................................................................................6 2.2 Équipe ....................................................................................................................................... 6 3 Préconisations....................................................................................................................................7 3.1 Version MySQL >= 5.1.46 Innodb plugin 1.0.7........................................................................ 7 3.2 Configuration InnoDB.............................................................................................................. 8 Dimension des Redo-log ............................................................................................................ 8 Dimension du Buffer Pool ......................................................................................................... 9 ACID .......................................................................................................................................... 9 3.3 max_connections....................................................................................................................... 9 3.4 Flush method............................................................................................................................10 3.5 Système configuration ............................................................................................................ 10 3.6 Index en double .......................................................................................................................10 3.7 Index non discriminants........................................................................................................... 11 Optimisation requêtes :..............................................................................................................11 3.8 Partitionnement ....................................................................................................................... 12 3.9 Scalabilité.................................................................................................................................13 Scalabilité en écriture/lecture....................................................................................................13 Scalabilité en lecture uniquement............................................................................................. 13 4 Sauvegarde/ Restauration................................................................................................................ 14 4.1 Mysqldump.............................................................................................................................. 14 4.2 Import – Export .......................................................................................................................15 4.3 Innodbhotbackup..................................................................................................................... 15 5 Architecture HA et continuité du service.........................................................................................15 MySQL réplication : asynchrone ............................................................................................ 16 5.1 MySQL Cluster ....................................................................................................................... 17 Tableau récapitulatif .................................................................................................................18 5.2 Bench et chargement de la base de données............................................................................ 18 5.3 Procédure , maintenance préventive........................................................................................ 19 6 Bonnes pratiques de développement............................................................................................... 19 EVITER LIKE %xx% sur de grosses tables............................................................................. 20 Eviter NULL ............................................................................................................................ 20 et les SELECT * (si possible).................................................................................................. 21 Eviter la fonction rand() dans les requête MySQL ................................................................ 21 Type de champs.........................................................................................................................21 Utiliser latin1 au lieu de utf8 ....................................................................................................22 Convertir blob et texte en varbinary et varchar ........................................................................22 Pagination et LIMIT N,M......................................................................................................... 24 Sous requêtes avec IN .............................................................................................................. 25 Copyright © 1995-2010, Oracle Corporation and/or its affiliates 3 / 38 CONFIDENTIAL Sous requêtes avec NOT IN..................................................................................................... 25 Index non utilisés...................................................................................................................... 26 Index manquants....................................................................................................................... 26 Index sur une partie d'un champ ............................................................................................. 27 Forcer l'ordre des jointures........................................................................................................28 Optimisation des ORDER BY.................................................................................................. 28 Optimisation des GROUP BY ..................................................................................................28 Transformer les sous requêtes en jointure :...............................................................................30 6.1 Réplication, liens utiles............................................................................................................31 7 Plan d'action.....................................................................................................................................33 8 Annexes........................................................................................................................................... 33 8.1 Plan stockage........................................................................................................................... 33 8.2 Multi instances......................................................................................................................... 35 8.3 Métrologie et montée en charge..............................................................................................35 8.4 Monitoring............................................................................................................................... 37 Bench avec Mysqlslap.............................................................................................................. 37 Copyright © 1995-2010, Oracle Corporation and/or its affiliates 4 / 38 CONFIDENTIAL 1.1 Contexte La mission d'expertise consiste à auditer l'installation, l'optimisation, tunning et l'architecture HA utilisés. L'audit a conduit à l'identification de plusieurs point à améliorer. Nous pouvons résumer les plus critiques par ordre d'importance : 1. La mise en place d'un serveur en stand by est recommandé pour la continuité du service en cas de crash du serveur MYSQL suite à une panne matérielles ou autres. 2. Un upgrade MySQL vers une version plus récente (>=5.1.47) ou au moins vers InnoDB plugin 1.0.7 est préconisé. 3. Les paramètres les plus critiques de configuration du serveur MySQL/InnoDB ont été discuté. 4. Attention, le ré-démarrage du serveur peut prendre un certains temps (jusqu'à 20mn et plus). Voir redo-log 5. Une installation de MySQL avec ubuntu a été effectué. Elle n'est pas recommandées. Elle est en retard de presque 2 ans (20 mois ) de plus elle n'a pas le plugin Innodb stable. 6. Une autre installation à partir du site MySQL a été réalisé et configuré pour Innodb plugin. 7. La sauvegarde a été optimisé 8. La maintenance préventive est à mettre en place 9. Certaines structures et index et requêtes sont à optimiser 10. La gestion des transactions est recommandé pour l'intégrité de la base. 11. La scalabilité est un des points fort bien discuté pour l'évolutivité de l'application 12. Pour la HA : la réplication est une solution qui a plus d'avantage par rapport à DRDB 13. Une optimisation après coup sur mesure de la production ou du contexte proche de la production est recommandé. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 5 / 38 CONFIDENTIAL 2 Informations administratives 2.1Client Client Nom du projet Adresse OUAT ENTERTAINMENT 197, rue de Bordeaux 16 000 Angoulême FRANC 2.2 Équipe Nom Compagnie Fabrice PASSAQUAY OUAT ENTERTA INMENT Zemrag Omar ORACLE / MySQL Position téléphone Courriel 05 45 38 40 15 fpassaquay@ouat+33 e.com 0177132703 Solution Architecte 33 6734842 62 [email protected] Note: Toutes recommandations fournis dans le présent rapport sont uniquement basées sur notre expérience générale . Nous vous conseillons de faire des tests avant toutes mise en pratique des recommandations sur un système de production. Garder en mémoire de faire une sauvegarde complète avant l'implémentation des changements préconisés. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 6 / 38 CONFIDENTIAL 3 Préconisations 3.1 Version MySQL >= 5.1.46 Innodb plugin 1.0.7 Recommandation : Nous vous recommandons d'installer >= MySQL 5.1.46 Innodb plugin 1.0.7 Gain : Les performance passe à plus de 10 – 300% entre InnoDB 5.0 avec Innodb plugin 1.0.7 (>MySQL 5.1.46) Procédure upgrade avec mysqldump : 1. sauvegarder vos données et vos binaires sauvegarde logique des bases de données et des users avec mysqldump stoper le serveurs mysql et sauvegardez à froid tous les repértoires de données et les fichiers de configuration (autant dire q'une sauvegarde globale est souhaité) Maintenant on une sauvegarde physique (servira pour un retour plus rapide) et une sauvegarde logique des données uniquement (qui servira pour l'upgrade aussi) 2. Installer le serveur MySQL 5.1.55 du serveur mysql wget du fichier .tar.gz tar -xzvf fichier .tar.gz suivre les étapes du fichier INSTALL configurer correctement le fichier my.cnf : Pour le multi instances : paramètres my.cnf à modifier basedir = /usr/local/mysql # binaire datadir = /var/lib/mysql # données pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 plus 2 variables d'environnement à mettre à jour pour travailler sur chaque instance MySQL_HOME= /var/lib/mysql PATH=usr/local/mysql:$PATH 3. redémarrer le serveur MYSQL utiliser le script mysql.server pour démarrer et stoper le service en mettant à jour : basedir=/usr/local/mysql datadir=/var/lib/mysql vérifier que le plugin est installé : show plugins; Copyright © 1995-2010, Oracle Corporation and/or its affiliates 7 / 38 CONFIDENTIAL 4. 5. 6. 7. importer le dump logique tester quelques opérations ouvrez le service sur dev et tester le ensuite ouvrer le service prod et vérifier le avant de l'ouvrir à grande échelle Configuration Innodb plugin [mysqld] ignore-builtin-innodb pluginload=innodb=ha_innodb_plugin.so;innodb_trx=ha_innodb_plugin.so;innodb_locks=ha_innodb_plugi n.so;innodb_lock_waits=ha_innodb_plugin.so;innodb_cmp=ha_innodb_plugin.so;innodb_cmp_reset= ha_innodb_plugin.so;innodb_cmpmem=ha_innodb_plugin.so;innodb_cmpmem_reset=ha_innodb_plugin. so innodb_file_format=barracuda innodb_file_per_table=1 Autres options lié à Innodb plugin à tester innodb_thread_concurrency=32 innodb_io_capacity=200 # InnoDB with the patch to use multiple background IO threads innodb_read_io_threads=4 innodb_write_io_threads=4 Gain : Les performance vont jusqu'à 35% plus que 5.1 avec Innodb plugin 1.0.7 Abstract : MySQL a été amélioré afin de profiter de la puissance des nouvelles architectures. La scalabilité et la performance s'en trouvent grandement amélioré. La version 5.1 apporte une nouvelle architecture basé sur les plugins. Les plugins permettent de charger ou décharger des librairies partagées dans une instance MySQL en cours d'exécution. Pour ajouter ou supprimer une fonctionnalité, faire un upgarde d'un moteur, on n'a plus besoin de compiler ou d'arrêter l'instance MySQL. Il suffit de charger ou décharger dynamiquement les plugins concernés. http://dev.mysql.com/doc/refman/5.1/en/pluginapi.html InnoDB plugin est une nouvelle version du moteur InnoDB qu'on peut utiliser à partir de la version MySQL 5.1.46. InnoDB 5.0 limite le nombre d'IO/s sur checkpoint a 100 IO/s de 16K ce qui nous amène à une écriture possible de 16x100=1600K/s. Théoriquement on peut aller jusqu'à 1600K/s. La version 5.1.46 en Innodb plugin n' a pas de limitation des IO sa capacité est donc limité uniquement par les capacités de votre infrastructure en entrée sortie (disques). http://www.innodb.com/products/innodb_plugin/features/ Copyright © 1995-2010, Oracle Corporation and/or its affiliates 8 / 38 CONFIDENTIAL 3.2 Configuration InnoDB Dimension des Redo-log Afin d'absorber les fortes charges en écritures et réduire le temps du restart du serveur MySQL, nous vous conseillons de choisir une valeur qui donne les performances satisfaisante sans alourdir de trop le ré-démarrage. Bencher le pour trouver la valeur optimale pour votre cas. Notre retour d'expérience donne une valeur généralement optimale pour 512M : 1G peut être trop haute ( à diviser par deux.) innodb_log_file_size=512M Note très importante : la taille des logs transactionnels influence le temps d'arrêt ou de redémarrage après crash. Attention pour modifier la taille des Redo log : stopper le serveur Avant de re-démarrer le serveur déplacer (et ne les supprimer que si tout va bien) les ib_log* base arrêtée pour appliquer un changement de taille. Re-démarrer le serveur MySQL Pour les esclave cette taille peut être encore augmenté Abstract : Il représente la taille des journaux innodb dans un groupe (2 par défaut) on recommande 25%-100% du buffer pool size. Dimension du Buffer Pool Afin d'absorber les fortes charges en lecture nous vous conseillons jusqu'à 80% de la RAM d'un serveur dédié. Le plus le mieux : innodb_buffer_pool_size=12 G ACID innodb_flush_log_at_trx_commit=1 Abstract : Pour plus de performances en écriture nous pouvons relâcher cette contrainte en paramétrant la valeur a 2. Les fsync assurant l'écriture physique par désactivation des caches ne seront exécutés que sur checkpoint et non plus lors de chaque COMMIT de transaction. Dans cette hypothèse au maximum 1 seconde d'écritures peuvent être perdu lors d'un arrêt brutal de la machine. Sur les esclaves réservé aux lectures cette valeur peut être relâché. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 9 / 38 CONFIDENTIAL 3.3 max_connections mysql> show status like '%used%'; +--------------------------------+-------+ | Variable_name | Value | +--------------------------------+-------+ | Max_used_connections | 517 | +--------------------------------+-------+ 6 rows in set (0.00 sec) Nous vous préconisons une valeur <900 vers une valeur que le serveur peut supporter. Cette valeur peut être benché : de 100 à 600 au maxi peut être une bonne valeur. 3.4 Flush method Généralement, on peut optimiser les IO avec cette option innodb_flush_method=O_DIRECT 3.5 Système configuration IO scheduler deadline Utiliser le IO scheduler deadline (ou noop) plutôt que celui par défaut (cfq) # vim /boot/grub/menu.lst # kopt = [...] elevator=deadline # update-grub # reboot Désactiver l'enregistrement du temps d'accès aux fichiers pour ext3 Dansl le fichier /etc/fstab, ajouter noatime aux options de montage. Exemple : /dev/sda1/ ext3 defaults,errors=remount-ro,noatime 0 Désactiver la mise en swap automatique après plus de 40% de mémoire vive utilisée : Dans le fichier /etc/sysctl.conf ,Ajouter/Modifier la ligne : sys.vm.swappiness = 0 Il est possible d'appliquer à chaud cette modification avec la commande : Copyright © 1995-2010, Oracle Corporation and/or its affiliates 10 / 38 CONFIDENTIAL # sysctl -p 3.6 Hardware CPU Pour une instance préférer la CPU la plus puissante surtout pour les slaves en stand by Disques Plus de disques vous donne plus d’options Eclater les données sur plusieurs disques afin d’augmenter les débits Nous recommandons l'utilisation du RAID10 avec des contrôleurs multi-canaux et une batterie de cache (BBU). Cependant le SAN constitue aussi une bonne solution. RAM Nous recommandons le plus de RAM possible pour couvrir la volumétrie active si possible 100% si non on au moins 25% du « working set » qui dépend de l'applicatif. 3.7 Index en double Priorité: moyenne Recommandation : supprimer les index en double : INDEX(A,B) et INDEX(A) INDEX(A) est inutile. Gain : + de performance Abstract : Pour accelérer ses recherche MySQL, peut utiliser un préfix (une sous partie gauche ) d'un index. Conséquence : lorsque un champ indexé INDEX(A) fait partie d'un préfixe gauche d'un autre index INDEX(A,B) celui ci (INDEX(A)) est inutile. Or un index en double consomme inutilement des ressources. A chaque mise à jour de la table, on doit mettre à jour des index en double. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 11 / 38 CONFIDENTIAL 3.8 Index non discriminants Recommandation : supprimer les index non discriminants et non utilisé Abstract : Les index doivent avoir une cardinalitée (Cardinality) forte (un index sur la civilité M, MME, MLLE ne sert absolument à rien) par contre un index sur un code regate est beaucoup plus discriminant. La commande ci-dessous permet de lister les index d'une table : mysql> SHOW INDEX FROM matable ATTENTION : un index avec une cardinalité faible peut être intéressant s'il est très sélectif sur une partie des données par exemple une table contenant des données actives (quelques centaines) et des données archives (quelques millions) peut avoir un index sur un booleen indiquant archive ou actif Note : une cardinalité faible peut être intéressante dans le cas ou il est placé en second d'un index composite (composé de plusieurs champs) : KEY (`nom`,`CIVILITE`) Optimisation requêtes : Eviter les focntion sur les clause where exemmple : monchamp & 1= 0 ou FROM_UNIXTIME( p.creation_date,'%Y-%m-%d') > DATE_SUB( '2010-10-27', INTERVAL 1 DAY) SELECT^M FROM_UNIXTIME(p.creation_date,'%Y/%m/%d %a') date,^M count(c.app_user_id) as counter,^M count(p.id)-count(c.app_user_id) as counter_bad^M FROM^M profiles p^M LEFT JOIN channels_app_users c ON c.app_user_id = p.id^M WHERE^M FROM_UNIXTIME( p.creation_date,'%Y-%m-%d') > DATE_SUB( '2010-10-27', INTERVAL 1 DAY)^M /* AND p.status != 1 AND p.status != 129 */^M GROUP BY date^M Copyright © 1995-2010, Oracle Corporation and/or its affiliates 12 / 38 CONFIDENTIAL ORDER BY date ASC; 3.9 Partitionnement Recommandation : Utiliser le partitionning sur les grosses tables Abstract : L’une des fonctions les plus intéressantes de MySQL 5.1 est son support du partitionnement horizontal des données, à la fois pour les tables et les index. Les principales formes de partitionnement sont supportées par les principaux moteurs de stockage de MySQL : Le partitionnement procure un certain nombre d’avantages : De meilleures performances – lors des opérations de balayage, l’optimiseur MySQL sait quelles sont les partitions contenant les données qui satisferont telle ou telle requête et n’accédera qu’à ces partitions lors de l’exécution de la requête. Par exemple, une table d’un million de lignes peut être divisée par plage en dix partitions différentes de façon que chacune d’entre elles contienne 100 000 lignes. Si une requête n’a besoin que des données d’une seule de ces partitions et qu’une opération de balayage de la table s’avère nécessaire, le système n’accédera qu’à 100 000 lignes au lieu d’un million. MySQL vérifiant évidemment plus vite 100 000 lignes qu’un million, la requête sera donc achevée bien plus tôt. • Une gestion des données simplifiée – le partitionnement permet aux DBA de mieux contrôler la façon dont les données sont gérées au sein de la base de données. En créant intelligemment des partitions, un DBA peut simplifier l’exécution de certaines opérations sur les données. Il peut par exemple supprimer certaines partitions d’une table partitionnée et laisser les autres intactes (plutôt que d’élaborer une opération de suppression en masse dans la table, génératrice de fragmentation) . Note : garder à l'esprit que le partitionning est nouveau dans MySQL 5.1. Il convient de le tester avec soins avant mise en production. Certaines fonctions évolués ne sont pas encore disponible. Par exemple, on ne peut pas ajouter une partition type range au milieu des partitions. On ne peut pas restaurer une partition supprimé sauf à passer par des insert classiques. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 13 / 38 CONFIDENTIAL 3.10 Scalabilité Scalabilité en écriture/lecture Pour scaller les écriture on utilise le partitionnement fonctionnel. Il s'agit de partager les données de manière horizontale. Le principe consiste à identifier des données indépendantes les unes des autres de manière à pouvoir les séparer sur une base de données dédiée. En cas de montée en charge on peut dédier à cette base de données une instance MySQL sur le même serveur hôte ou sur un autre hôte dédié. De cette manière on peut scaller chaque base de données de manière efficace et économique. On s'adapte de manière plus fine et plus flexible à chaque type de données. De plus la fiabilité et la performance se trouvent amélioré (un crash d'une base pas d'effet sur les autres bases, les cash sont plus stable) les stats peuvent être dirigé sur une autre instance (même en MyISAM) Les tables liés aux objets à l'exception de my_objects peuvent être dédié à une instance Remarque : Cacher les données objets lié à un user sur une web serveur est recommandé. On peut dédier une instance à chaque type d'usage exemple : les utilisateur qui s'enregistre pour la première fois et qui font des recherches. Cela nécessite plus d'effort au niveau du désign en fonction des possibilités de l'applicatif. Scalabilité en lecture uniquement Généralement, on rencontre en premier, un besoin en scalabilité en lecture. La réplication MySQL en asynchrone native a été largement déployé pour répondre à ce besoin. La scalabilité en lecture est facile avec MySQL il suffit d'ajouter des esclaves Read Appli scalabilite Lecture Write 7 7 11 12 12 replication Copyright © 1995-2010, Oracle Corporation and/or its affiliates 14 / 38 CONFIDENTIA Les écritures et les lectures qui ne tolère aucun décalage ne peuvent pas être scallées. 4 Sauvegarde/ Restauration 4.1 Mysqldump L'option --single-transaction sur toutes les bases permet de prendre une image cohérente de la base et pénalise moins le serveur MySQL mysqldump -uroot -p'xxxxxxxxx' -h"126.X.Y.Z" blob --add-drop-database > dump.Sql --single-transaction --all-databases --hex- avec la réplication : mysqldump -uroot -p'xxxxxxxxx' -h"126.X.Y.Z" --single-transaction --master-data=2 --flushlogs --triggers --routines --all-databases --hex-blob --add-drop-database > dump.Sql master-data pour générer la synchronisation avec les log-bin flush-logs crée un nouveau fichier bin log Avec Innodb, utiliser single-transaction Gain : données intègres, sauvegardes non blocantes Remarque avec MyISAM utiliser lock-all-tables : compte tenu de la nom utilisation des transactions, pour garder l'intégrité de la base il faut locker toutes les tables Impact: Attention le service se dégrade(InnoDB) voir indisponible (MyISAM) pendant la sauvegarde. Le cache du serveur a été modifié pour la sauvegardes (On peut éventuellement le réchauffer après la sauvegrade) La restauration des données se fait par un client mysql mysql -uroot -p'xxxxxxxxx' <dump.sql Copyright © 1995-2010, Oracle Corporation and/or its affiliates 15 / 38 CONFIDENTIA 4.2 Import – Export La commande LOAD DATA INFILE lit les lignes dans un fichier texte et les insère à très grande vitesse. Pour plus d'informations sur l'efficacité des commandes INSERT comparativement à LOAD DATA INFILE et pour accélérer les commandes LOAD DATA INFILE, voyez Section 7.2.14, « Vitesse des requêtes INSERT ». Vous pouvez aussi charger des fichiers de données en utilisant l'utilitaire mysqlimport; Il opère en envoyant la commande LOAD DATA INFILE au serveur. L'option --local fait que mysqlimport lit les fichiers de données chez le client. Vous pouvez spécifier l'option --compress pour avoir de meilleurs performances avec les connexions lentes si le client et le serveur supportent le protocole compressé. See Section 8.10, « mysqlimport, importer des données depuis des fichiers texte ». Pour la commande LOAD DATA INFILE sur des fichiers du serveur, vous devez avoir le droit de FILE sur le serveur. See Section 5.5.3, « Droits fournis par MySQL ». Utiliser LOCAL est plus lent que de laisser le serveur accéder directement aux fichiers, car le contenu du fichier doit être envoyé via le réseau au serveur. D'un autre coté, vous n'aurez pas besoin de droits de FILE pour faire un chargement local. Depuis MySQL 3.23.49 et MySQL 4.0.2 (4.0.13 sur Windows), LOCAL fonctionne uniquement si votre serveur et votre client ont été configuré pour. Par exemple, si mysqld a été lancé avec --local-infile=0, LOCAL ne fonctionnera pas. See Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL » 4.3 Innodbhotbackup Innodbhotbackup peut être plus rapide qu'une alimentation par requête replace ou load data http://www.innodb.com/products/hot-backup/order/ 5 Architecture HA et continuité du service Généralement, on rencontre en premier, un besoin de HA en lecture. La réplication MySQL en asynchrone native a été largement déployé pour répondre à ce besoin. Dans des cas ou on souhaite la haute disponibilité à moindre cout avec un risque de perte de données cette solution a aussi été utilisé en master-master, actif-passif (dual master). Pour les applications OLTP classiques qui ne tolèrent aucun décalage ni perte de données nous recommandons DRBD/HeartBeat. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 16 / 38 CONFIDENTIA • • • • • Le principaux avantage de la réplication / DRDB : Facilité de prise en main et très utilisé dans le web. Esclave peut être utilisé : pour les lecture, reporting, pour les réorganisations, les upgrades, les sauvegardes en ligne, les upgarde, l'exploitation est facilité ... Certaine erreur humaines ou corruptions de données ne seront pas propagé à l'esclave ( ex: dd sur un file système du master n'affectera pas l'esclave) En cas de fail-over Il n'est pas nécessaire de faire un recover avec InnoDB performance et scalabilité en lecture plus facile Un des inconvénients /DRDB : volume de données (data seulement) en double, risque de perte ou décalage de données avec de la vidéo en ligne Remarque : Notez que DRDB que est une autre solution open source très utilisé avec MySQL est supporté par ORACLE/MySQL. MySQL réplication : asynchrone VIP s1 Write Read Actif Passif m1 m2 Avantages Facile à configurer et à utiliser Inconvénients Fail-over manuel ou passage par heartbeat Réplication natives depuis MySQL 3.23 Latence et perte de donnée possible Indépendant du moteur Nécessite un monitoring Slave peut être promu maitre facilement Fail-over rapide Slave peut être utilisé en lecture Slave peut être optimisé pour la lecture Copyright © 1995-2010, Oracle Corporation and/or its affiliates 17 / 38 CONFIDENTIA Peut être utilisé pour le disaster recovery (réplication géographique) Possibilité de maintenance en ligne en dual master : réorganisation en ligne, suavegarde en ligne, upgrade en ligne, ... On peut ajouter de répliquants très facilement Enormément de fonctionnalité avancée ( filtrer les bases de données, réplication semi-synchrones, ...) Moins sujet à la propagation des corruption (bug en maj seulement) 5.1 MySQL Cluster MySQL Cluster est la vraie solution de haute disponibilité, scalable en lecture et en écriture. MySQL Cluster est excellent en forte concurrence sur beaucoup de transaction courtes. C'est très utilisé dans les télécoms. Elle permet de faire des upgrade en ligne, ... Cependant MySQL Cluster présente quelques limitations qui peuvent être contourné soit nativement (réécritures des requêtes complexes) soit en utilisant un moteur adapté (comme le moteur InnoDB) en parallèle au sein du même serveur ou sur un serveur dédié En séparant le reporting du transactionnel on peut dédier le transactionnel au Cluster . Avantages Scalable horizontalement et verticalement automatiquement Inconvénients Configuration complexe Load balancing natif et automatique Nécessite de revoir certaines jointures complexes Le cout est plus élevé Nécessite un réseau performant Volumétrie des données doit être maitrisé Foregin Key non géré Nécessite au moins 3 machines Upgrade en ligne Sauvegarde en ligne SAN non obligatoire Copyright © 1995-2010, Oracle Corporation and/or its affiliates 18 / 38 CONFIDENTIA Tableau récapitulatif Archi Existants Perte de donnée Durée fail-over MySQL Cluster Non Non <1s Réplication Oui Oui* 30s à 1h** DRBD NON Non 30s à 30mn SAN/heartbeat NON Non 30s à 30mn *Les données perdu dépend de l'application et du hardware **Avec perte de données, le temps de bascule dépend du réseau et du décalage entre le slave et le maitre 5.2 Procédure , maintenance préventive Pour répondre rapidement aux requêtes utilisateurs, les SGBD font des mise à jours sans effectuer un ordonnancement complet des tables. Les données sont éparpillés. La réorganisation permet de supprimer les trous éventuels , réordonne la table et les index et met à jour les statistiques (nécessaire à l'optimiseur). Copyright © 1995-2010, Oracle Corporation and/or its affiliates 19 / 38 CONFIDENTIA Nous vous recommandons de réorganiser régulièrement les tables au moins une fois par semaine surtout pour les tables qui bougent très souvent suite aux update, delete, ... Soit avec un client mysql : mysql:root:dbtest> optimize table matable; +----------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +----------------+----------+----------+----------+ | dbtest.matable | optimize | status | OK | +----------------+----------+----------+----------+ 1 row in set (0.00 sec) mysql:root:dbtest> Soit avec le programme mysqlcheck mysqlcheck dbtest matable -o dbtest.matable OK Impact: cette action lock les tables et risque de dégrader fortement les performances voir un arrêt du service. A lancer lorsque le serveur est en ligne et peux ou pas du tout sollicité par les applicatifs. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 20 / 38 CONFIDENTIA 6 Bonnes pratiques de développement Type de champs Utiliser les types les plus petits possibles. ■ http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html ■ Privilégier les dates en format TIMESTAMP ■ Passage des champs contenant des valeurs statiques en Enum ou en set http://dev.mysql.com/doc/refman/5.0/en/set.html http://dev.mysql.com/doc/refman/5.0/en/enum.html Analyse la structure optimale de la table pour une requête donnée minimum/maximum de la longueur et de la valeur compte de la valeur NULL et des valeurs zéro et vides valeur moyenne et écart type Suggère le type optimal du champ mysql> SELECT name,population FROM city -> WHERE population > 250000 -> PROCEDURE ANALYSE(8, 256) \G ************* 1. row ****************** Field_name: world.city.Name Min_value: Aba Max_value: +skemen Min_length: 3 Max_length: 30 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 8.3807 Std: NULL Optimal_fieldtype: VARCHAR(30) NOT NULL ************* 2. row ****************** Field_name: world.city.Population Min_value: 250121 Max_value: 10500000 Min_length: 6 Max_length: 8 Empties_or_zeros: 0 Nulls: 0 Copyright © 1995-2010, Oracle Corporation and/or its affiliates 21 / 38 CONFIDENTIA Avg_value_or_avg_length: 802699.3768 Std: 1155068.8492 Optimal_fieldtype: MEDIUMINT(8) UNSIGNED NOT NULL Types courants de la colonne : Nom : CHAR(35) NOT NULL Population : INTEGER NOT NULL Utiliser latin1 au lieu de utf8 Il est plus performant de mettre les bases en latin1. utf8 peut potentiellement prendre 3 fois plus de place selon les cas. Convertir blob et texte en varbinary et varchar Toute requête sur un champ blob et texte qui requière des tables temporaires se feront sur disque d'où la dégradation des performances. a-Enlever les type blob et les type text dans la selection b-Les transformer en varchar maxi 65535 par table : 65535 doit etre partagé sur toutes les colonnes d'une table et depend du caracter set. Pour utf8 le max est de 21844 Type Stockage requis* Longueur max. (en caract.) CHAR Taille de colonne max. 255 VARCHAR Taille de la valeur + 1-2 octets 65 535** TINYTEXT Taille de la valeur + 1 octet 255 TEXT Taille de la valeur + 2 octets 65 535 MEDIUMTEXT Taille de la valeur + 3 octets 16 777 215 LONGTEXT Taille de la valeur22+/ 438octets Copyright © 1995-2010, Oracle Corporation and/or its affiliates 4 294 967 295 CONFIDENTIA * La taille de chaque caractère dépend du jeu de caractères. ** La taille max. dépend du varchar de tous les type de colonnes de la table . La requête sur les metadata pour generer les champ de type blob et texte select TABLE_NAME,TABLE_SCHEMA,COLUMN_NAME,DATA_TYPE from columns WHERE (DATA_TYPE like '%text%' or DATA_TYPE like '%blob%') and TABLE_SCHEMA NOT IN ('mysql','information_schema') order by 1; Exemple : SELECT SQL_NO_CACHE a.*,(CASE a.tri_manuel WHEN 999 THEN (recherche.pertinence + (a.tri_auto / 25)) ELSE (recherche.pertinence * (25 + (1/a.tri_manuel))) END ) as popularite_pertinence , recherche.* FROM (SELECT count(*) nb_resultats , SUM(CASE mcp.id_mot_cle WHEN 33453 THEN mcp.poids / 1.65 WHEN 86180 THEN mcp.poids / 2.72 WHEN 319 THEN mcp.poids / 4.48 WHEN 1720 THEN mcp.poids / 7.39 WHEN 14262 THEN mcp.poids / 12.18 ELSE mcp.poids / EXP(5*0.5) END) pertinence,p.id_type_page,p.id_page_type FROM rech__mot_cle_page mcp,rech__page p WHERE p.id_page = mcp.id_page AND mcp.id_mot_cle IN (33453,86180,319,1720,14262) AND p.id_page = mcp.id_page GROUP BY p.id_page HAVING pertinence>=250 ORDER BY nb_resultats DESC ) as recherche , articles_enligne a, types_articles ta Cette requête crée des tables temporaires mysql> select max(length( ref_alt)), max(length(libelle)), max(length(description)), max(length(specs_FR)), Copyright © 1995-2010, Oracle Corporation and/or its affiliates 23 / 38 CONFIDENTIA max(length(specs_EN)), max(length(specs_IT)), max(length(points_forts)), max(length(visu_galerie)) from marchand.articles_enligne -> \G *************************** 1. row *************************** max(length( ref_alt)): 41 max(length(libelle)): 57 max(length(description)): 2033 max(length(specs_FR)): 6564 max(length(specs_EN)): 6564 max(length(specs_IT)): 6564 max(length(points_forts)): 488 max(length(visu_galerie)): 244 1 row in set (0.08 sec) ces champs fde marchand.articles_enligne peuvent être mis en varchar : ref_alt → v archar(50) ... analyse EVITER LIKE %xx% sur de grosses tables SELECT sql_no_cache expression_lisible as mot FROM rech__historique WHERE expression_lisible IS NOT NULL AND expression_saisie LIKE '%tomtom%' Eviter NULL Déclarer les champs des tables avec NOT NULL par défaut sauf si la valeur NULL a un sens pour votre application. et les SELECT * (si possible) Copyright © 1995-2010, Oracle Corporation and/or its affiliates 24 / 38 CONFIDENTIA Eviter la fonction rand() dans les requête MySQL Exemple d'algo pour random : pré-génerer d'avance des valeurs aléatoires et les utiliser − − − − ajouter une colonne indexée appelé « aleatoire » alimenté de manière aléatoire utiliser order by aleatoire au lieu de order by rand() une fois une ligne seléctionnée mettez la à jour par une autre valeur aléatoire mettez périodiquement les valeurs aléatoires quand c'est nécessaire Une autre technique ; − − − − SELECT MAX(rowid) AS maxrowid FROM t1 LIMIT 1; (INNODB) Excécuter random() function en php pour retourner une valeur X entre 0 et MAX(rowid) SELECT col FROM t1 WHERE rowid >=X Si 0 lignes retourné changer de direction dans le WHERE Exemple : select sql_no_cache tmp.* FROM (SELECT expression_saisie FROM rech__historique WHERE auto=0 AND id_TA_dominant=18 ORDER BY popularite_manuelle DESC,popularite_auto DESC LIMIT 0,20) as tmp ORDER BY RAND() LIMIT 0,10 ; Pagination et LIMIT N,M Priorité: haute Recommandation : Nous vous recommandons d'éviter les requêtes avec 2 paramètres LIMIT N,M. Privilégier LIMIT M avec 1 seul paramètre (sans OFFSET) Abstract : Afin de limiter le nombre d'enregistrement retourné, il est possible d'utiliser la clause LIMIT. Il faut faire très attention si on utilise la clause LIMIT avec 2 paramètres (LIMIT X, Y) avec X numéro de la première occurrence à retourner, Y nombre d'occurrences à retourner car le select * from matable LIMIT 10000,20 va nécessiter à mysql de parcourir 10020 enregistrement et pas 20 comme on pourrait le penser. Il faut donc privilégier l'utilisation de LIMIT avec un seul paramètre. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 25 / 38 CONFIDENTIA Note : Attention à l'ordre dans le limit Le limit s'effectue sur la dernière requête et pas sur l'ensemble des requetes Trouver une technique de pagination sans OFFSET exemple : Page suivante : WHERE id < 200 /* dernier */ ORDER BY id DESC LIMIT $taille_page /* Plus d'offset */ Page Prec : WHERE id > 190 /* dernier */ ORDER BY id DESC LIMIT $taille_page /* Plus d'offset */ Sous requêtes avec IN Priorité: haute Recommandation : Réécrire les requêtes lentes de type : SELECT col FROM t1 WHERE id_col IN (SELECT id_col2 FROM t2 WHERE condition); En : SELECT col FROM t1, t2 WHERE t1.id_col = t2.id_col AND condition; Abstract : Les jointures sont généralement plus rapide par rapport aux sous-requêtes. Les sous requêtes ont été ajouté à MySQL depuis MySQL 5.0. Elles font encore l'objet d'optimisation dans les prochaines versions MySQL. Sous requêtes avec NOT IN Priorité: moyenne Recommandation : Réécrire les requêtes lentes de type : Copyright © 1995-2010, Oracle Corporation and/or its affiliates 26 / 38 CONFIDENTIA SELECT t1.* FROM t1 WHERE t1.i NOT IN (SELECT i FROM t2 WHERE condition) En : SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.i = t2.i AND condition WHERE t2.i IS NULL Abstract : Les jointures sont généralement plus rapide par rapport aux sous-requêtes. Les sous requêtes ont été ajouté à MySQL depuis MySQL 5.0. Elles font encore l'objet d'optimisation dans les prochaines versions MySQL. Index non utilisés Priorité: haute Recommandation : Supprimez un index non utilisé même s'il est sélectif. Abstract : Si aucune requêtes n'utilise l'index, il alourdit les mise à jour pour rien. On ne peut pas savoir actuellement ,si un index est utilisé ou non sauf si on connait toutes les requêtes utilisateurs. Le moniteur (avec le Query anlayser) et le log général permettent de recenser toutes les requêtes. Attention c'est consommateur de ressources, à utiliser avec beaucoup de précaution. Ils (Log général et QUAN) dégradent les performances. Index manquants Priorité: haute Recommandation : Ajouter des index quand c'est possible pour des requêtes lentes Abstract : Certaine requêtes lentes peuvent être accélérer par l'ajout d'un index. Cela nécessite d'analyser le plan d' exécution des requêtes : Exemple : mysql:> explain select * from t1 where i=1; +----+-------------+-------+------+---------------+------+--------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | Copyright © 1995-2010, Oracle Corporation and/or its affiliates 27 / 38 CONFIDENTIA +----+-------------+-------+------+---------------+------+--------+------+------+-------------+ | 1 | SIMPLE | t1 | ALL | NULL | NULL | NULL | NULL | 600000 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) Cette requête fait un ballayage de toute la table ( 600000 lignes) En ajoutant un index mysql:> ALTER TABLE t1 ADD INDEX (i); on ne balaie plus que 2 lignes en utilisant l'index sur i mysql> explain select * from t1 where i=1; +----+-------------+-------+------+---------------+------+--------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+--------+-------+------+-------+ | 1 | SIMPLE | t1 | ref | i | i | 4 | const | 2 | | +----+-------------+-------+------+---------------+------+--------+-------+------+-------+ 1 row in set (0.00 sec) Impact: refonte appli Delai : Durée de création de table (demande 2h) Index sur une partie d'un champ Priorité: moyenne Recommandation : Créer un index sur une partie du champ discriminante – Indexer les n premiers caractères d'un champs de type texte Exemple si les 20 premiers caractères sont discriminants ajouter un index sur 20 char Copyright © 1995-2010, Oracle Corporation and/or its affiliates 28 / 38 CONFIDENTIA mysql:> ALTER TABLE t1 ADD INDEX (monchamp(20)); Abstract : Objectifs – Minimiser la taille de l'index – Ces n caractères doivent être suffisamment discriminants – CREATE INDEX pref_index ON ma_table(col_text(30)); L'index est d'autant plus performante qu'il est en plus petit.(mais suffisamment discriminant) Forcer l'ordre des jointures Quelquefois l' optimiseur fait un choix plus lent : SELECT STRAIGHT_JOIN colx FROM A,B WHERE A.COL1=B.COL2 Couverture d'une requete par un index SELECT qte WHERE id=27 –Index sur (id,qte) utilise l'index et évite d'aller lire sur la table Optimisation des ORDER BY Couvrir par un index si possible SELECT qte FROM art WHERE id=27 ORDER BY type –Index sur (id,type) utilise l'index et évite de faire un tri en passant par une table temporaire En mémoire il utilise le buffer sort_buffer_size Utiliser LIMIT si possible Optimisation des GROUP BY •Utilisez SQL_BIG_RESULT si les données à regouper sont volumineuse (évite de créer une table temporaire mais utilise filesort) •SELECT Fonction Agragation(B) FROM TBL GROUP BY A Indexer sur (A,B) •Ajouter ORDER BY NULL si vous n'avez pas besoin d' ordre MySQL trie par défaut les GROUP BY Exemple : Copyright © 1995-2010, Oracle Corporation and/or its affiliates 29 / 38 CONFIDENTIA mysql> explain select SUM( (TR.quantity * ( TR.price * TR.currencyRate ) ) - ( TR.drm * TR.currencyRate ) ) AS FromBegin, TP.* FROM t_producteur TP LEFT JOIN tRoyalties TR ON TR.idProducer = TP.id_producteur where TP.accountManager=66 GROUP BY TP.producteur order by TP.producteur\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: TP type: ref possible_keys: accountManager key: accountManager key_len: 5 ref: const rows: 62 Extra: Using where; Using temporary; Using filesort *************************** 2. row *************************** id: 1 select_type: SIMPLE table: TR type: ref possible_keys: idProducer,idx_p key: idx_p key_len: 2 ref: TP.id_producteur rows: 765 Extra: 2 rows in set (0.00 sec) Eviter les tables temporaire (Using temporary+Using filesort)+ et trie en ajoutant un index : KEY `accountManager_2` (`accountManager`,`producteur`) mysql> alter table t_producteur add index accountManager_2(`accountManager`,`producteur`); Query OK, 2871 rows affected (0.36 sec) Records: 2871 Duplicates: 0 Warnings: 0 mysql> explain select SUM( (TR.quantity * ( TR.price * TR.currencyRate ) ) Copyright © 1995-2010, Oracle Corporation and/or its affiliates 30 / 38 CONFIDENTIA - ( TR.drm * TR.currencyRate ) ) AS FromBegin, TP.* FROM t_producteur TP LEFT JOIN tRoyalties TR ON TR.idProducer = TP.id_producteur where TP.accountManager=66 GROUP BY TP.producteur order by TP.producteur\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: TP type: ref possible_keys: accountManager,accountManager_2 key: accountManager_2 key_len: 5 ref: const rows: 64 Extra: Using where *************************** 2. row *************************** id: 1 select_type: SIMPLE table: TR type: ref possible_keys: idProducer key: idProducer key_len: 4 ref: TP.id_producteur rows: 313185 Extra: 2 rows in set (0.00 sec) Transformer les sous requêtes en jointure : Mysql> explain select idSong FROM tSongHistory WHERE idSong IN (SELECT id_song FROM t_song WHERE id_album = '20210' AND dateStart = '2009-02-27')\G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: tSongHistory type: index possible_keys: NULL key: unique_idSong_dateStart key_len: 7 ref: NULL rows: 365677 Extra: Using where; Using index *************************** 2. row *************************** Copyright © 1995-2010, Oracle Corporation and/or its affiliates 31 / 38 CONFIDENTIA id: 2 select_type: DEPENDENT SUBQUERY table: t_song type: unique_subquery possible_keys: PRIMARY,id_album key: PRIMARY key_len: 4 ref: func rows: 1 Extra: Using where 2 rows in set (0.01 sec) Ici la requête va scanner 365677 lignes avec Jointure scan d'une seule ligne mysql> explain select idSong FROM tSongHistory a, t_song b WHERE id_album = '20210' AND dateStart = '2009-02-27' AND a.idSong=b.id_Song\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: b type: ref possible_keys: PRIMARY,id_album key: id_album key_len: 4 ref: const rows: 1 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: a type: eq_ref possible_keys: unique_idSong_dateStart key: unique_idSong_dateStart key_len: 7 ref: b.id_song,const rows: 1 Extra: Using index 2 rows in set (0.00 sec) • • 6.1 Si possible remplacer IN par des requêtes avec UNION ALL Eviter les fonctions et les expressions dans les clauses where Réplication, liens utiles http://dev.mysql.com/doc/refman/5.0/en/show-slave-status.html http://dev.mysql.com/doc/refman/6.0/en/replication-semisync.html http://forge.mysql.com/wiki/ReplicationFeatures/SemiSyncReplication Copyright © 1995-2010, Oracle Corporation and/or its affiliates 32 / 38 CONFIDENTIA http://forge.mysql.com/wiki/ReplicationTeam 1. Note Importante : Toutes recommandations fournis dans le présent rapport sont uniquement basées sur notre expérience générale . Nous vous conseillons de faire des tests avant toutes mise en pratique des recommandations sur un système de production. Garder en mémoire de faire une sauvegarde complète avant l'implémentation des changements préconisés. Copyright © 1995-2010, Oracle Corporation and/or its affiliates 33 / 38 CONFIDENTIA 7 Plan d'action Priorité 1 2 3 4 5 6 7 8 Description Upgarde MySQL >=5.1.47 Stand By Continuite de service Optimisation structure et requêtes Mise en place des optimize Monitoring à mettre en place évolutivité HA en replication Architecture en multi instance – multi serveur Tunning en situation de production en cas de blocakage Issues Date prod % compl 9 Nous sommes à votre disposition pour vous aider à mettre en place ce plan d'action. 8 Annexes 8.1 Plan stockage Nous vous recommandons de mettre en place un plan de stockage normalisé. Il devra séparer les log des data. Volumes des données /deploy/<instancename>/var/ (my.cnf,pid,.sock) bases, table spaces, iblog* /logbin/ /log/ (slowlog, errlog, ...) /relaylog/ /tmp/ Les répertoires var, tmp, logbin, relaylog peuvent être mis sur des disques différents On peut aussi utiliser SSD pour datadir : /var rapide en accès direct et les HDD (moins couteux) pour les journaux en accès séquentiel 1) performance : la possibilité de configurer les composants d'une manière souple facilite les optimisations. En parallélisant et en aiguillant chaque type d'entrée sortie au harware adéquat. Les caches MySQL se trouve plus optimisées. 2) indépendance : Le plan de nommage permet d'installer, faire fonctionner, administrer, et faire évoluer les serveurs MySQL indépendamment des OS : UNIX/Linux, ubuntu redhat, … 3) évolutivité : le découpage doit être suffisamment souple pour éviter d'être remis en cause à la suite d'upgrade applicatifs, versions, systèmes, ... Volumes des binaires /myq/v-<x.x.x>/ (binaires) (pointe sur les binaires) /mysql-pro-gpl-5.1.23-pc-10-x86_64/ /dba/ (dba scripts : create user, create database ...) /expl/(backup,purges, reorg..) /appli / (applications scripts) /log /tmp /agentMySQL Volumes des données /deploy/<instancename>/var/ (my.cnf,pid,.sock) bases, table spaces, iblog* /logbin/ /log/ (slowlog, errlog, ...) /relaylog/ /tmp/ Les répertoires var, tmp, logbin,relaylog peuvent être mis sur des disques différents Volumes des sauvegardes /backup/<instancename>/froid/ /chaud/ 8.2 Multi instances Nous préconisons du multi-instances : Avantages multi instances: Indépendance des instances : flexibilité et fiablilité renforcé une application qui plante une instance n'affecte pas les autres Mutualisation plusieurs applications peuvent cohabiter Upgardes facilitées Retoure en arrière plus simple admin os sur une seule machine au lieux de plusieurs cout en licence moins élévé Implémentation du partitionning fonctionnel et du sharding possible sans avoir à acheter d'autres machines, Inconvénient nécessite un investissement initial pour mettre en place une configuration d'un environnement multi-instance 8.3 Métrologie et montée en charge Pour mesurer la montée en charge nous vous recommandé l'outil Jmeter. C' est un outil qui permet de valider le bon fonctionnement d’une application dans son contexte. Il est développé par la Fondation Apache, en tant que sous projet Jakarta. JMeter permet : 1. la concurrence des requêtes de tests durant le tir de charge ou bien d’avoir des paliers de tests en termes d’utilisateurs virtuels. 2. d’avoir des robots injecteurs pour simuler la charge tout en la répartissant sur plusieurs machines injecteurs (et ainsi éviter que le goulot d’étranglement soit le poste de test). On peut tester : * Les temps de réponses d’une application web, en fonction du nombre d’utilisateurs virtuels * Les écarts de temps de réponse en fonction de paliers d’utilisateurs * Les différences de comportements d’une même application sur deux (ou plus) environnements d’exécution différents (par exemple cluster ou non, configuration 1 / configuration 2, etc) * La robustesse d’une application (à partir de quand la solution s’interrompt brutalement (crash) ?…) * Le fonctionnellement une application de manière automatique (tests de non régression, de validité fonctionnelle, etc) * Superviser une application (soit via une sorte de ‘ping’, soit par des éléments plus complexes). 8.4 Monitoring Pramètre OK ALETE CRITIQUE DOWN en % 100 *( max_connections – threads_connected )/ max_connections en % <50 et >20 <=20 <50 et >20 <=20 created_disk_tmp_tables*100/created_tmp_tables, >10 >40 Slow_Queries /(Com_select + Qcache_hits+Com_insert+Com_update+Com_delete+ Com_replace) >10 50 espace disque dispo en pourcentage pour chaque partition data, logbin, relaylog, backup <50 <20 0 io wait (vmstat mpstat) >10 >40 >100 cpu >50 >80 >100 vmstat si so >0 >0 100 *( max_connections – Max_used_connections max_connections )/ Nous vous conseillons d'utiliser MySQL Monitor. Bench avec Mysqlslap Mysqlslap est fournis avec mysql 5.1. Voici un exemple de bench innodb #!bin/sh list="2 4 8 16 32" quer=100000 quer=10000 for i in $list do mysqlslap --user=root -plaposte --auto-generate-sql \ --concurrency=$i --number-of-queries=$quer \ --number-char-cols=4 --number-int-cols=7 --engine=innodb \ --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=mixed iterations=2 done --mysql-user=root run