web-dev-qa-db-fra.com

Gérer les bogues non reproductibles

Supposons que votre équipe écrit un système logiciel qui fonctionne (de manière assez surprenante).

Un jour, l'un des ingénieurs exécute par erreur des requêtes SQL qui modifient certaines des données de la base de données, puis les oublie.

Après un certain temps, vous découvrez les données corrompues/erronées et tout le monde se gratte la tête pour savoir quelle partie du code a causé cela et pourquoi, en vain. Pendant ce temps, le chef de projet insiste pour que nous trouvions la partie du code qui l'a causé.

Comment gérez-vous cela?

72
Nik Kyriakides

Il est évident qu'aucun chef de projet n'investira une quantité infinie de temps dans un tel problème. Ils veulent éviter que la même situation ne se reproduise.

Pour atteindre cet objectif, même si l'on ne parvient pas à trouver la cause profonde d'un tel échec, il est souvent possible de prendre certaines mesures pour

  • Détectez ces défaillances plus tôt au cas où elles se reproduiraient
  • Rendez moins probable que le même échec se reproduise
  • Rendre le système plus robuste contre le type spécifique d'incohérence

Par exemple, une journalisation plus détaillée, une gestion des erreurs plus fine ou une signalisation immédiate des erreurs pourraient aider à empêcher la même erreur de se reproduire ou à trouver la cause première. Si votre système autorise l'ajout de déclencheurs de base de données, il est peut-être possible d'ajouter un déclencheur qui empêche en premier lieu l'incohérence.

Réfléchissez au type d'action approprié dans votre situation et suggérez-le à l'équipe; Je suis sûr que votre chef de projet sera ravi.

Un jour, l'un des ingénieurs exécute par erreur des requêtes SQL qui modifient certaines des données de la base de données, puis les oublie.

Comme mentionné par d'autres, c'est également une bonne idée d'interdire une telle procédure (si vous avez une influence sur le fonctionnement du système). Personne ne doit être autorisé à exécuter des requêtes ad hoc non documentées qui modifient le contenu de la base de données. Si une telle requête est nécessaire, assurez-vous qu'il existe une stratégie pour stocker la requête avec sa date d'exécution, le nom de la personne qui l'a exécutée et la raison pour laquelle elle a été utilisée, dans un endroit documenté.

134
Doc Brown

Ce n'est pas un bug

Du moins pas sur votre code. C'est un bug dans votre processus. Votre chef de projet devrait être beaucoup plus préoccupé par votre processus que votre code.

Comment gérez-vous cela?

Tout simplement, en ne laissant pas les ingénieurs modifier les bases de données de production ou de développement partagées .


En supposant qu'il s'agit d'une base de données de développement partagée:

Idéalement, si possible, évitez d'avoir une base de données partagée en premier lieu . Au lieu de cela, ayez des bases de données par développeur de courte durée. Cela devrait être automatisé avec des scripts, sinon le coût du test devient trop élevé et il y a une incitation à ne pas tester les choses. Vous pouvez avoir ces bases de données sur le poste de travail du développeur ou sur un serveur central.

Si, pour une raison quelconque, vous DEVEZ absolument avoir une base de données partagée, vous devez utiliser fixtures - essentiellement, quelque chose qui place la base de données dans un état connu à chaque fois que vous devez l'utiliser. Cela évite aux développeurs d'être mordus par les changements des autres.

Si vous devez appliquer des modifications permanentes à la base de données, vous devez les valider dans votre contrôle de code source . Configurez votre base de données de manière à ce que les développeurs n'aient pas la permission d'y écrire directement et ayez un programme qui extrait les modifications du contrôle de code source et les applique.

Enfin, d'après votre description de la façon dont vous déboguez, il semble que vous n'utilisez pas CI . Utilisez CI . C'est un peu pénible à installer, mais cela vous fera économiser SO beaucoup de temps à long terme, sans parler de vous empêcher de vous inquiéter des bogues de base de données non reproductibles. Vous n'aurez qu'à vous inquiéter à propos de heisenbugs maintenant!


En supposant qu'il s'agit d'une base de données de production:

Si vos développeurs changent les bases de données de production, beaucoup de choses ont horriblement mal tourné, même si les changements sont absolument corrects.

Les développeurs ne doivent jamais accéder aux bases de données de production . Il n'y a absolument aucune raison, et tant de choses qui peuvent aller très très mal.

Si vous avez besoin de réparer quelque chose dans une base de données de production, commencez par sauvegarder, restaurez cette sauvegarde sur une instance différente (développement), et puis jouer autour de cette base de données de développement. Une fois que vous pensez avoir un correctif prêt (sur le contrôle de code source!), Vous recommencez la restauration, appliquez le correctif et voyez le résultat. Ensuite, après avoir sauvegardé à nouveau les choses (et empêché idéalement les mises à jour simultanées), vous corrigez l'instance de production, idéalement via un correctif logiciel.

Si vous devez tester quelque chose dans une base de données de production ... non, vous ne le faites pas. Quels que soient les tests que vous devez faire, vous devez le faire dans une instance de développement. Si vous avez besoin de certaines données pour effectuer les tests, vous obtenez ces données là-dedans.

50
goncalopp

Une base de données de production doit avoir une journalisation d'accès complet et des contrôles d'accès basés sur les rôles. Ainsi, vous devriez avoir des preuves tangibles quant à QUI a fait QUOI QUAND à la base de données, déplaçant ainsi l'attention du code vers une sécurité opérationnelle médiocre.

13
Don Gilman

Dans ce cas, vous avez finalement trouvé la cause, mais en prenant votre hypothèse que vous n'avez pas ...

Analysez d'abord ce qui a changé. Si le système fonctionnait correctement auparavant, un examen attentif de tout ce qui a été fait récemment pourrait révéler le changement à l'origine du bogue. Examinez systématiquement votre contrôle de version, vos systèmes de déploiement/CI et votre contrôle de configuration pour voir si quelque chose a changé. Exécutez git bisect ou un mécanisme équivalent pour effectuer une recherche binaire. Vérifiez les journaux. Cherchez des journaux que vous ne saviez pas avoir. Parlez à tous ceux qui ont accès au système pour voir s'ils ont fait quelque chose récemment. Pour votre problème, si vous êtes suffisamment approfondi dans ce processus, cela devrait, espérons-le, révéler les requêtes SQL oubliées.

Deuxièmement, l'instrumentation. Si vous ne pouvez pas trouver directement la cause d'un bogue, ajoutez de l'instrumentation autour de lui pour recueillir des données sur le problème. Demandez-vous "si je pouvais reproduire ce bogue sur commande, que voudrais-je regarder dans le débogueur", puis enregistrez-le. Répétez au besoin jusqu'à ce que vous compreniez mieux le problème. Comme le suggère Doc Brown, ajoutez la journalisation pour les états pertinents pour le bogue. Ajoutez des assertions qui détectent les données corrompues. Par exemple, si votre bogue est un crash d'application, ajoutez un mécanisme de journalisation des plantages. Si vous en avez déjà un, super, ajoutez des annotations aux journaux de plantage pour enregistrer l'état potentiellement pertinent pour le plantage. Déterminez si des problèmes de concurrence peuvent être impliqués et test pour exercer la sécurité des threads .

Troisièmement, la résilience. Les bogues sont inévitables, alors demandez-vous comment vous pouvez améliorer vos systèmes pour être plus résilients afin que la récupération à partir du bogue soit plus facile. Vos sauvegardes pourraient-elles être améliorées (ou existantes)? Meilleure surveillance, basculement et alertes? Plus de redondance? Une meilleure gestion des erreurs? Découpler les services dépendants les uns des autres? Pouvez-vous améliorer vos processus concernant l'accès à la base de données et les requêtes manuelles? Au mieux, ces choses rendront les conséquences de votre bug moins graves, et au pire, ce sont probablement de bonnes choses à faire de toute façon.

6
Zach Lipton
  1. Expliquez à votre chef de projet que vous pensez que la cause le plus probable est l'accès manuel à la base de données.
  2. S'ils veulent toujours que vous recherchiez le code qui a provoqué cela, allez jeter un œil au code.
  3. Revenez dans quelques heures (ou à une autre heure appropriée) et dites que vous ne pouvez trouver aucun code qui aurait pu causer cela, donc vous pensez toujours que la cause la plus probable est l'accès manuel à la base de données.
  4. S'ils encore veulent que vous cherchiez le code, demandez combien de temps ils aimeraient que vous y passiez. Rappelez-leur subtilement que vous ne travaillerez pas sur la fonctionnalité X, le bug Y ou l'amélioration Z pendant que vous faites cela.
  5. Passez autant de temps qu'ils le demandent. Si vous pensez toujours que la cause la plus probable est l'accès manuel à la base de données, dites-le-lui.
  6. S'ils encore veulent que vous cherchiez le code, faites remonter le problème car cela est clairement devenu une utilisation improductive du temps de votre équipe.

Vous pouvez également vous demander si vous devez ajouter des processus supplémentaires pour réduire la probabilité d'un accès manuel à la base de données entraînant ce type de problème à l'avenir.

5
Philip Kendall

Je travaillais dans l'équipe de développement d'un produit de base de données mainframe lorsqu'un client a signalé qu'il avait une base de données corrompue. Une corruption dans le sens où l'état interne des bits sur le disque signifiait que la base de données n'était pas lisible via le logiciel de base de données. Dans le monde mainframe, les clients vous paient des millions de dollars et vous devez prendre cela au sérieux. Voilà ce que nous avons fait:

Étape 0: aidez le client à se remettre en marche en réparant la base de données.

Étape 1: en examinant le fichier sur disque au niveau hexadécimal, nous avons déterminé que la corruption était systématique: il y avait de nombreux cas de la même corruption. Cela a donc été définitivement causé au niveau du logiciel de base de données. En effet, il était suffisamment systématique pour que nous pensions pouvoir écarter les problèmes de multi-threading.

Après avoir éliminé de nombreuses autres théories, nous avons intégré un utilitaire qui pourrait être utilisé pour la réorganisation physique de la base de données. Il semble que ce soit le seul code qui ait accès aux données au bon niveau. Nous avons ensuite découvert un moyen d'exécuter cet utilitaire, avec des options soigneusement sélectionnées, qui reproduisaient le problème. Le client n'a pas pu confirmer ou nier que c'était ce qu'il avait fait, mais comme c'était la seule explication que nous pouvions trouver, nous avons décidé que c'était la cause probable, et ils n'avaient d'autre choix que d'accepter notre diagnostic .

Étape 2: Nous avons ensuite apporté deux modifications au logiciel: (a) il a été plus difficile de provoquer cet effet accidentellement via une interface utilisateur "oui je sais ce que je fais", et (b) en introduisant un nouveau fichier journal afin que si cela s'est jamais reproduit, nous aurions un enregistrement des actions de l'utilisateur.

Donc, fondamentalement (a) réparer les dommages et restaurer le fonctionnement en direct, (b) trouver la cause profonde, (c) faire tout ce qui est nécessaire pour éviter que cela ne se reproduise ou pour permettre un diagnostic facile si cela se reproduit.

4
Michael Kay

D'après mon expérience, ce que votre patron veut, c'est une certaine assurance de niveau que cela ne se reproduira pas. S'il est vrai qu'aucun code n'a été la cause, car cela est assuré par des tests d'unité, donc en supposant que vous avez déjà une couverture de test sur votre base de code, la solution devrait ajouter "testing" à votre base de données. Je vais citer Don Gilman, car il y a cloué:

Une base de données de production doit avoir une journalisation d'accès complet et des contrôles d'accès basés sur les rôles. Ainsi, vous devriez avoir des preuves tangibles quant à QUI a fait QUOI QUAND à la base de données, déplaçant ainsi l'attention du code vers une sécurité opérationnelle médiocre.

Mais vous devez également avoir une procédure standard d'exploitation sur la modification des données en production. Par exemple, aucun administrateur de base de données ne devrait modifier les données, aucun développeur ne devrait exécuter le changement lui-même et ils devraient, comme défini dans le SOP, exiger les uns des autres formellement le changement par courrier ou ticket.

Il doit y avoir une citation comme ça quelque part, sinon vous pouvez me citer dessus:

Il y a une bonne raison pour laquelle les chefs ne sont pas responsables du nettoyage des toilettes.

3
CesarScur

Il y a plusieurs choses à faire avec les bugs non reproductibles.

  1. Créez un ticket pour cela

Créez un ticket et enregistrez tout ce à quoi vous pouvez penser dans le ticket. Vérifiez également si ce "bug" a été enregistré auparavant, et liez les tickets ensemble. Finalement, vous pouvez obtenir suffisamment de tickets pour établir un modèle de reproduction du bogue. Cela inclut les contournements utilisés pour essayer de l'éviter. Même si c'est le seul exemple, s'il y a une première fois, il y aura éventuellement une deuxième fois. Lorsque vous trouvez la cause, fermez le ticket avec une explication de la cause afin d'avoir une idée précise de ce qui s'est produit si cela se reproduit (correction perdue lors d'une mauvaise fusion)

  1. Faire une analyse de durcissement

Regardez le système, ce qui a échoué et comment il a échoué. Essayez de trouver les zones du code qui peuvent être mises à jour pour rendre l'échec moins probable. Quelques exemples...

  • Remplacez le code ad hoc par un appel dédié (comme execute(<query>) par executeMyStoredProcedure(<params>)
  • Exécutez des scripts de vérification nocturnes pour vérifier l'intégrité des données (afin que cela puisse être détecté dans les 24 heures la prochaine fois)
  • Ajouter/améliorer la journalisation et l'archivage (sauvegarde).
  • Modifier les limites de sécurité inappropriées (par exemple, les personnes/programmes qui ne lisent que des données n'ont pas de permission d'écriture; ne pas permettre aux développeurs qui ne sont pas responsables de la production de pouvoir se connecter aux serveurs de production)
  • Ajouter la vérification/l'assainissement des données là où il manque

Cela ne résoudra peut-être pas le bogue, mais même si ce n'est pas le cas, le système est maintenant plus stable/sécurisé, il est donc toujours rentable.

  1. Ajouter des alertes système

Cela fait un peu partie de 2, mais quelque chose s'est produit, et vous devez savoir quand cela se reproduira. Vous devez créer des scripts/programmes de contrôle d'intégrité pour surveiller le système, afin que les administrateurs puissent être alertés dans les 24 heures suivant le resurfaçage du bogue (moins il y a de retard, mieux c'est, dans des limites raisonnables). Cela rendra le nettoyage beaucoup plus facile. (Notez qu'en plus des journaux des bases de données, le système d'exploitation doit également consigner les utilisateurs qui s'y connectent et toutes les actions non lues qu'ils effectuent. À tout le moins, il doit y avoir des journaux réseau du trafic vers cette machine)

1
Tezra

Votre problème n'a pas été causé par une erreur dans votre logiciel, mais par quelqu'un qui tripote la base de données. Si vous appelez les choses qui vont mal un "bug", alors votre bug est facilement reproductible: Les choses vont toujours mal quand quelqu'un fait des choses stupides à la base de données. Et il existe des moyens d'éviter ce "bug", en ne permettant pas la modification manuelle de la base de données ou en utilisant un logiciel non testé, et en contrôlant strictement qui peut modifier la base de données.

Si vous appelez uniquement les défauts dans votre base de données un "bug", alors vous n'avez pas de bug irréproductible, vous n'avez aucun bug du tout. Vous pouvez avoir un rapport de bogue, mais vous avez également la preuve que le problème n'a pas été causé par un bogue. Vous pouvez donc fermer le rapport de bogue, non pas comme "irreproductible", mais quelque chose d'autre comme "base de données endommagée". Il n'est pas rare d'avoir des rapports de bogues où l'enquête montre qu'il n'y a pas de bogue, mais un utilisateur a mal utilisé le logiciel, ses attentes étaient fausses, etc.

Dans ce cas, vous savez toujours qu'il y a un problème que vous ne souhaitez pas répéter, vous devez donc prendre la même action que dans le premier cas.

0
gnasher729