Archive pour August 2007

Sécurité PHP 5 et MySQL

Tuesday 28 August 2007

Je viens de lire rĂ©cemment SĂ©curitĂ© PHP 5 et MySQL, Ă©crit par Damien Seguy et Philippe Gamache. J’ai Ă©videment commencĂ© par les parties que me tiennent Ă  coeur, MySQL et en particulier:

  • Risques liĂ©s aux bases de donnĂ©es
  • VulnĂ©rabilitĂ©s des base de donnĂ©es
  • Mesures de sĂ©curitĂ© pour MySQL

Je vous le conseille, vous trouverez un condensĂ© de tout ce qu’il faut savoir Ă  ce sujet pour protĂ©ger vos bases de donnĂ©es. Merci messieurs!
Je vais m’attaquer Ă  la partie PHP :)

ProblĂšme de verrou?

Tuesday 28 August 2007

J’ai eu un petit problĂšme sympa Ă  rĂ©soudre. En rĂ©sumĂ©, nous avons 2 tables t1 et t2.

mysql> select * from t1;
+——+——+
| id | name |
+——+——+
| 1 | a |
| 2 | b |
| 3 | ab |
| 4 | bc |
+——+——+

mysql> select * from t2;
+————–+———+
| dependent_id | base_id |
+————–+———+
| 1 | 1 |
| 3 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 3 | 2 |
| 4 | 2 |
+————–+———+

Nous ouvrons une transaction (T1) et nous exĂ©cutons la requĂȘte suivante.

SELECT * FROM t1 JOIN t2 WHERE t1.id=t2.dependent_id AND t2.base_id=1 FOR UPDATE;

+——+——+————–+———+
| id | name | dependent_id | base_id |
+——+——+————–+———+
| 1 | a | 1 | 1 |
| 3 | ab | 3 | 1 |
+——+——+————–+———+

Nous ouvrons une transaction (T2) et nous exĂ©cutons la requĂȘte suivante.

SELECT * FROM roles WHERE id=2 FOR UPDATE;

Et alors que les 2 requĂȘtes ne sont pas sensĂ©es travailler sur les mĂȘme lignes, T2 attend la fin de T1? Comment est ce possible?

Pour comprendre vous devez analyser le plan d’exĂ©cution.

mysql> explain SELECT * FROM t1 JOIN t2 WHERE t1.id=t2.dependent_id AND t2.base_id=1 FOR UPDATE;

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 7 | Using where |
| 1 | SIMPLE | t1 | ALL | PRIMARY | NULL | NULL | NULL | 3 | Using where |

Voila l’erreur, MySQL fait un full table scan (type ALL) pour exĂ©cuter cette requĂȘte et ainsi bloque toutes les lignes. T2 est ainsi obliger d’attendre la fin de T1. Pourquoi?

Ayant seulement 4 entrĂ©es dans cette table, l’optimiseur de MySQL prĂ©fĂšre un faire un full table scan plutot qu’utiliser un index. De la j’ ai insĂ©rĂ© d’autre entrĂ©e dans la table t1, et le plan d’exĂ©cution a changĂ©.

| 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 217 | Using where |
| 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | t2.dependent_id | 1 | |

MySQL bloque ainsi seulement la PK et fait bien du ‘row level locking’. T2 peut aboutir sans problĂšme. CQFD!

Kaj repond Ă  Mike et Jeremy…

Thursday 9 August 2007

Kaj rĂ©agit aux discussions d’hier. Mais qu’est ce que cela va changer pour le user landa? Va-t-il se tourner vers la version enterprise? Sachant que j’ai encore des serveurs qui tournent MySQL du 3.23, du 4.0 et du 4.1, cette restructuration aura-t-elle un impact pour moi? Non je ne crois. Pour des grosses sociĂ©tĂ©s, tous les bugs sont trouvĂ©s en phase de test… si la version courante est buggĂ©, je prendrais la prĂ©cĂ©dente.

des nouveautés sur MySQL Enterprise vs Community

Thursday 9 August 2007

Les annonces faites par Kaj ont secoué un peu la communauté avec des réactions assez forte de ses membres actifs. Je vous laisserez les lire en détails sur son blog.
Mais voila l’idĂ©e gĂ©nĂ©rale:

  • Les patchs et les nouvelles fonctionnalitĂ©s ne seront plus appliquĂ© Ă  la GA mais attendront la version suivante.
  • 2 GA par an pour ce qui est des binaires
  • pour les nouvelles versions 1 GA par mois jusqu’Ă  maturation
  • 4 GA par an pour ce qui est des sources
  • Les sources des versions “entreprise” ne seront disponibles que pour les clients payant

Suite à cela pas mal de réactions, en autres de la part de Mike et Jeremy à ce sujet.

Maintenant quoi penser de la chose? Techniquement, MySQL est open source et pas free source. MySQL a Ă©tĂ© portĂ© par sa communautĂ© et c’est ce qui a fait que cette BdD soit devenu si populaire. On ne peut pas s’empĂȘcher de penser Ă  la mĂȘme sĂ©paration qu’il y a eu lieu entre RHEL et Fedora. A la diffĂ©rence que les patchs et fixs sont d abord appliquĂ©s sur FC et que les versions stabilisĂ©es sortent ensuite sur RHEL.

Seconds_behind_master?

Thursday 2 August 2007

Lorsque vous faites un SHOW SLAVE STATUS pour savoir l’Ă©tat d’un de vos slaves dans votre chaĂźne de rĂ©plication, vous avez cet intĂ©ressant paramĂštre Seconds_behind_master, ceci Ă©videmment si vous utilisez MySQL 4.1 et plus. Sur un serveur j’ai eu la dĂ©sagrĂ©able surprise de voir cette valeur alterner constamment entre 0 et 2 heures…Humm? Ceci m’a poussĂ© Ă  regarder plus en dĂ©tail le calcul de cette valeur.

Quand un slave se connecte au master, par la entendez le Slave I/O thread, il enregistre la valeur dm = SELECT UNIX_TIMESTAMP() ce qui revient Ă  connaĂźtre la date actuelle du master (dm: date master) puis fait la mĂȘme chose sur lui mĂȘme ds = SELECT UNIX_TIMESTAMP() (ds: date slave). De la il calcule la diffĂ©rence D = ts - tm.

Dans les log de rĂ©plication (binlog) sont enregistrĂ©s les dates d’exĂ©cutions de chaque requĂȘte. Ainsi lorsque le Slave SQL thread rejoue ces mĂȘme requĂȘtes, il calcule:

seconds_behind_master = SELECT UNIX_TIMESTAMP() sur le slave - date d’exĂ©cution de la requĂȘte sur le master - D

Premier point, ce paramĂštre nous donne la diffĂ©rence entre le moment oĂč une requĂȘte est mise dans le relay log et le moment ou elle a Ă©tĂ© executĂ© sur le master. En aucun cas nous connaissons le temps qu’il a fallu pour la rĂ©cupĂ©rer du master. Donc imaginons maintenant que votre slave est lent Ă  les rĂ©cupĂ©rer mais une fois rĂ©cupĂ©rĂ©es, elles soient exĂ©cutĂ©es instantanĂ©ment… Votre valeur Seconds_behind_master sera 0 alors qu’en rĂ©alitĂ© votre slave peut ne pas ĂȘtre Ă  jour.

Quand le SQL thread est au niveau, pas d’autre relay log Ă  jouer, Seconds_behind_master sera 0. Si votre connexion rĂ©seau est rapide, le slave I/O thread sera proche du masteret donc ce champ vous donnera une bonne approximation. Dans le cas contraire, le valeur sera 0 car le SQL thread est en attente du I/O thread et non car votre slave est Ă  jour.

NULL est un autre valeur possible pour ce champ, si l’I/O thread est en pause ou en train de se reconnecter, celle valeur est mise Ă  NULL.

En rĂ©sumĂ©, celle valeur est informative et peut Ă©ventuellement vous mettre sur la piste d’un problĂšme rĂ©seau mais elle n’est pas Ă  prendre pour argent comptant.