Bonjour,
Je développe une application à l'aide du Zend Framework et rencontre quelques "problèmes" dans la gestion de la base de données liés à l'architecture de cette dernière.
En effet, pour faire simple, cette dernière s'architecture autour d'une multitude de serveurs répliqués de la manière qui suit :
Ainsi, les Masters sont accessibles en Lecture/Ecriture, tandis que les Slaves ne le sont qu'en lecture. Des requêtes de MAJ se feront donc sur les Masters tandis que des simples requêtes de lectures se feront sur les Slaves. Un "répartiteur", permet, en fonction de la charge des machines, de répartir le flux vers tel ou tel serveur. Dès qu'une mise à jour est détectée, les Masters se synchronisent entre eux et synchronisent les Slaves de manière avoir des données homogènes et cohérentes. Voici pour l'architecture simplifiée, j'espère avoir été compréhensible...
Au niveau du code désormais, sont gérés des logs applicatifs. Le modèle BDD simplifié est le suivant :
Lorsqu'une requête est effectuée, son accès est loggué dans la table Requete et l'identifiant est récupéré. Les paramètres sont loggué dans la table ParametresRequete (avec la référence vers Requete grace à l'id récupéré), idem pour les éventuelles erreurs. Une série de traitement est effectuée pour créer les résultats à retourner et ces derniers sont loggués dans la table RésultatsRequete (avec la aussi la référence vers Requete).
Le problème qui se pose est le suivant. Nous avons en moyenne entre 2 et 4 requêtes à la seconde, et donc autant de logs. Parmi cs nombreux logs ressortent quelques erreurs d'insertion BDD (à hauteur de 0.015%, ce qui est ridicule je vous l'accorde, mais j'aimerais comprendre...). Cette erreur d'insertion est la suivante :
Comme on peut le voir, ce qui plante est l'insertion dans la table de résultat en cause de la référence vers la table de requete. Il tente en effet d'insérer dans résultat une référence vers une requete qui n'existe pas, d'où l'erreur. Mais alors pourquoi donc, étant donné qu'il n'y a aucune raison à ce que la requête n'ait pas été correctement insérée ? Nos investigations nous poussent à croire, et c'est la première fois que le cas se présente, que le problème est liée à l'architecture BDD mise en place, ou au fonctionnement interne de Zend, tout dépend le point de vue :-). En effet, dans la théorie, le log de requete est bien inséré en base de données, mais sur l'un des serveur Master. L'architecture BDD fait que les masters doivent alors se synchroniser entre eux. Sauf que, les requêtes étant très nombreuses et le laps de temps entre l'insertion requête/résultats très court, il semblerait que la synchro n'est pas eu le temps de s'effectuer. Pour le peu que la répartition de la charge fasse que le log de résultat se fasse alors sur le second Master, non encore synchronisé, il tente alors en effet de référer sur une requete qu'il ne connait pas encore...
Code : Sélectionner tout - Visualiser dans une fenêtre à part SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`ResultatsRequete`, CONSTRAINT `fk_resultatsrequete_requete` FOREIGN KEY (`ref_id_resultats_requete`) REFERENCES `Requete` (`id_requete`) ON DELETE CASCADE ON UPDATE CASCADE)
La question que nous nous posons, en ce qui concerne Zend, est alors pourquoi ce dernier créé-t-il une autre connexion BDD et ne conserve-t-il pas la même ? (si la même était conservée, il aurait alors écris sur le même serveur). A quel moment est donc effectuée la connexion vers la base de données ? Lors de la création de chacun des objets Mappers ou DbTable ? N'y a-t-il aucun moyen de lui spécifier d'encapsuler un ensemble d'opérations BDD dans une même connexion, même si cet ensemble d'opérations utilise une multitude de DbTable différents ? La mise en place d'une transaction pourrait-elle régler le problème ?
L'architecture BDD mise en place a été longuement pensée et réfléchie pour pouvoir gérer l'énorme charge qu'elle subit et palier les éventuels défaut d'un serveur, d'où cette réplication. Il n'est donc pas envisageable de la revoir par nos amis NAS. D'où la recherche d'une solution au niveau dev.
Merci pour toutes les suggestions que vous pourrez m'apporter.
Partager