Lidando com bugs não reproduzíveis


73

Suponha que sua equipe escreva um sistema de software (surpreendentemente!) Funcionando bem.

Um dia, um dos engenheiros executa erroneamente algumas consultas SQL que alteram alguns dos dados do banco de dados e depois esquece.

Depois de algum tempo, você descobre os dados corrompidos / errôneos e todos pensam em qual parte do código causou isso e por que, sem sucesso. Enquanto isso, o gerente de projetos insiste em encontrar a parte do código que o causou.

Como você lida com isso?


32
Se o engenheiro esqueceu disso, como você sabe que foi isso que aconteceu? Como você foi corrompido por alguém executando um script, e não por um bug?
DaveG 25/10

18
Ele teve uma epifania depois de um dia ou dois. Isso é hipotético, caso ele nunca se lembre do que poderia ter sido facilmente o caso.
Nik Kyriakides

12
Isso é hipotético. Tenho certeza que o primeiro-ministro nos faria perseguir isso, o máximo que pudermos, se ele nunca se lembrasse. Eu sei que sim.
Nik Kyriakides 25/10

59
xkcd.com/583 ;) [idioma NSFW]
Baldrickk

100
"Suponha que sua equipe escreva um sistema de software que esteja funcionando bem." Pare de me provocar com fantasias impossíveis!
Paul D. Waite

Respostas:


134

É óbvio que nenhum gerente de projeto investirá uma quantidade infinita de tempo nesse problema. Eles querem impedir que a mesma situação aconteça novamente.

Para atingir esse objetivo, mesmo que não seja possível encontrar a causa raiz de tal falha, muitas vezes é possível tomar algumas medidas para

  • Detecte essas falhas mais cedo, caso elas ocorram novamente
  • Torne menos provável que a mesma falha aconteça novamente
  • Tornar o sistema mais robusto contra o tipo específico de inconsistência

Por exemplo, registros mais detalhados, manipulação de erros mais refinada ou sinalização imediata de erros podem ajudar a impedir que o mesmo erro ocorra novamente ou a encontrar a causa raiz. Se o seu sistema permitir adicionar gatilhos de banco de dados, talvez seja possível adicionar um gatilho que proíba a inconsistência introduzida.

Pense no tipo de ação apropriado para sua situação e sugira isso à equipe; Estou certo de que seu gerente de projetos ficará satisfeito.

Um dia, um dos engenheiros executa erroneamente algumas consultas SQL que alteram alguns dos dados do banco de dados e depois esquece.

Conforme mencionado por outros, também é uma boa idéia proibir esse procedimento (se você tiver influência sobre como o sistema é operado). Ninguém deve ter permissão para executar consultas ad-hoc não documentadas que alteram o conteúdo do banco de dados. Se houver necessidade dessa consulta, verifique se existe uma política para armazenar a consulta junto com sua data de execução, o nome da pessoa que a executou e o motivo pelo qual ela foi usada, em um local documentado.


8
@NicholasKyriakides Provavelmente ambos. Todas essas são medidas de senso comum para simplificar a depuração "adiada". Eles provavelmente foram escritos em inúmeros procedimentos.
22818 Nic Hartley

29
Ocasionalmente, você tem algum tipo de problema sério em um sistema de produção e falha na determinação da causa, apesar de um esforço significativo. Por fim, você o atribui a raios cósmicos e tenta melhorar a geração de relatórios (por isso, se acontecer novamente, você terá mais chances de encontrar a causa) e mitigação (por isso, se acontecer novamente, o dano será mínimo) e verificará se repete.
David Schwartz

2
@Nicholas Kyriakides: experiência pessoal ao longo de várias décadas.
Doc Brown

4
Também deve ser observado que é muito possível que, mesmo que houvesse um bug, ele não estivesse mais lá. Às vezes, o melhor que você pode fazer é corrigir os dados e aprimorar os testes / procedimentos para garantir que o mesmo problema não ocorra novamente.
kutschkem

2
Encontrar problemas intermitentes tem tudo a ver com o registro e encontrar um ponto de estrangulamento que possa detectá-los à medida que ocorrem, e depois andar para trás a partir daí para identificar a fonte. Às vezes, isso requer coisas desagradáveis, como gatilhos ou implantação de código com registro de erros barulhento, apenas para controlar o momento e o local do erro.
AaronLS 26/10

51

Isso não é um bug

Pelo menos não no seu código. É um bug no seu processo . Seu gerente de projeto deve estar muito mais preocupado com o seu processo do que com o seu código.

Como você lida com isso?

Simplesmente, não permitindo que os engenheiros alterem os bancos de dados de produção ou desenvolvimento compartilhado .


Supondo que este seja um banco de dados de desenvolvimento compartilhado:

Idealmente, se possível, evite ter um banco de dados compartilhado em primeiro lugar . Em vez disso, tenha bancos de dados por desenvolvedor de curta duração. Isso deve ser automatizado com scripts, caso contrário, o custo para testar se torna muito alto e há um incentivo para não testar as coisas. Você pode ter esses bancos de dados na estação de trabalho do desenvolvedor ou em um servidor central.

Se, por algum motivo, você DEVE absolutamente ter um banco de dados compartilhado, deve usar equipamentos - essencialmente, algo que defina o banco de dados para um estado em bom estado toda vez que você precisar usá-lo. Isso evita que os desenvolvedores sejam mordidos pelas mudanças de outras pessoas.

Se você precisar aplicar alterações permanentes ao banco de dados, confirme-as com seu controle de origem . Configure seu banco de dados de forma que os desenvolvedores não tenham permissão para gravá-lo diretamente e tenha um programa que retire as alterações do controle de origem e as aplique.

Por fim, a partir de sua descrição de como você está depurando as coisas, parece que você não está usando o IC . Use o IC . É um pouco trabalhoso de configurar, mas economizará muito tempo a longo prazo, sem mencionar que você não precisa se preocupar com erros improdutíveis no banco de dados. Agora você só precisa se preocupar com heisenbugs !


Supondo que este seja um banco de dados de produção:

Se seus desenvolvedores estão alterando os bancos de dados de produção, muitas coisas deram errado, mesmo que as alterações estejam absolutamente corretas.

Os desenvolvedores nunca devem acessar bancos de dados de produção . Não há absolutamente nenhuma razão para isso, e tantas coisas que podem dar muito errado.

Se você precisar consertar algo em um banco de dados de produção, primeiro faça o backup, restaure esse backup em uma instância diferente (de desenvolvimento) e, em seguida, execute esse banco de dados de desenvolvimento. Depois de pensar que você tem uma correção pronta (no controle de origem!), Refaça a restauração, aplique a correção e veja o resultado. Depois, depois de fazer o backup novamente (e, idealmente, evitar atualizações simultâneas), você corrige a instância de produção, idealmente através de um patch de software.

Se você precisa testar algo em um banco de dados de produção ... não, não precisa . Quaisquer que sejam os testes que você precisa fazer, você deve fazer em uma instância de desenvolvimento. Se você precisar de alguns dados para fazer os testes, você os incluirá lá.


12
Então, sua solução recomendada é viajar no tempo?
21718 Benubird

7
Embora essa seja uma solução decente para o exemplo dado, a questão tem um contexto muito mais geral de como lidar com bugs que não podem ser reproduzidos e com os gerentes que desejam que eles os persigam. Isso pode se aplicar a muito mais do que apenas problemas de banco de dados e gerenciamento de permissões. Sinto que essa resposta não responde realmente à pergunta pretendida, apenas o exemplo dado.
Kyle Wardle

@KyleWardle concordou. Acho que a resposta do Doc Brown cobre muito bem o caso geral (registro detalhado e tratamento de erros, condições de guarda). Eu, principalmente, acrescentou minha, porque não vi ninguém tinha mencionado as falhas de processos que levaram ao problema em primeiro lugar
goncalopp

2
@Benubird Eu acho que a resposta se resume a "a maneira como você lida com isso está impedindo que isso aconteça novamente". Eu não acho que você possa "resolver" um banco de dados de produção corrompido da perspectiva da engenharia de software.
Goncalopp 26/10/19

11
Você não vai alterar o código para colocar dados no banco de dados dev. Em todos os lugares em que trabalhei, incluindo grandes corporações, os desenvolvedores são livres para inserir dados de teste e usar as mesmas credenciais que o aplicativo usa.
David Conrad

13

Um banco de dados de produção deve ter registro de acesso completo e controles de acesso baseados em função. Portanto, você deve ter evidências concretas sobre a OMS O QUE QUER QUANDO no banco de dados, deslocando assim a atenção do código para uma segurança operacional ruim.


2
Parece que eles podem não saber exatamente quando ocorreu a corrupção dos dados, o que pode dificultar a identificação de quais logs eles precisam investigar.
Nathanael

3
Infelizmente, ao rastrear um desses, descobrimos que ele também estava destruindo os logs. (. Sim, Ele o bug foi real.)
Joshua

O registro de casal com trabalhos agendados que verificam a integridade dos dados, mesmo que apenas durante a noite, significa que os problemas podem ser sinalizados antecipadamente e resolvidos. Se você quiser ser realmente cuidadoso, exija a revisão por pares para alterações.
261 Keith

Em todos os lugares em que trabalhei, os desenvolvedores se conectam ao banco de dados com as mesmas credenciais que o aplicativo usa, para que o log de acesso seja exibido apenas quando esse ID tiver feito a alteração, não que tenha sido feito por um ser humano e não por um programa. Suponho que você possa comparar o registro de data e hora com os logs do aplicativo para ver se o aplicativo estava fazendo algo que gravaria no banco de dados naquele momento.
David Conrad

@DavidConrad: Por que os desenvolvedores têm acesso às credenciais que o aplicativo usa na produção? Você deve usar algum tipo de gerenciamento secreto para que essas credenciais nem possam ser lidas, exceto pela sua conta de serviço de aplicativo, dos servidores de aplicativos de produção.
Daniel Pryden # 03:

6

Nesse caso, você finalmente descobriu a causa, mas considerando sua hipótese de que não ...

Primeiro, analise o que mudou. Se o sistema estava funcionando bem antes, uma análise cuidadosa de tudo o que foi feito recentemente pode revelar a alteração que causou o erro. Revise sistematicamente seu controle de versão, sistemas de IC / implantação e controle de configuração para ver se alguma coisa mudou. Execute git bisect ou um mecanismo equivalente para executar uma pesquisa binária. Verifique os logs. Procure por logs que você não sabia que tinha. Converse com todos com acesso ao sistema para ver se eles fizeram algo recentemente. Para o seu problema, se você for minucioso o suficiente nesse processo, esperamos que isso revele as consultas SQL esquecidas.

Segundo, instrumentação. Se você não conseguir encontrar diretamente a causa de um bug, adicione instrumentação para coletar dados sobre o problema. Pergunte a si mesmo "se eu pudesse reproduzir esse bug sob comando, o que eu gostaria de ver no depurador" e registre-o. Repita conforme necessário até entender melhor o problema. Como sugere Doc Brown, adicione o registro de estados relevantes para o bug. Adicione asserções que detectam dados corrompidos. Por exemplo, se o seu bug é um travamento de aplicativo, adicione um mecanismo de log de travamento. Se você já possui um ótimo, adicione anotações aos logs de falha para registrar o estado potencialmente relevante para a falha. Considere se problemas de simultaneidade podem estar envolvidos e teste para exercer a segurança da thread .

Terceiro, resiliência. Os erros são inevitáveis; portanto, pergunte-se como você pode melhorar seus sistemas para que sejam mais resilientes, para que a recuperação do bug seja mais fácil. Seus backups poderiam ser melhorados (ou existentes)? Melhor monitoramento, failover e alerta? Mais redundância? Melhor tratamento de erros? Desassociar serviços dependentes um do outro? Você pode melhorar seus processos de acesso ao banco de dados e consultas manuais? Na melhor das hipóteses, essas coisas tornarão as consequências do seu bug menos graves e, na pior das hipóteses, provavelmente serão boas ações a serem feitas.


5
  1. Explique ao seu gerente de projeto que você acha que a causa mais provável é o acesso manual ao banco de dados.
  2. Se eles ainda querem que você procure o código que causou isso, vá e dê uma outra olhada no código.
  3. Volte em algumas horas (ou em algum outro momento apropriado) e diga que não encontra nenhum código que possa ter causado isso; portanto, você ainda acredita que a causa mais provável é o acesso manual ao banco de dados.
  4. Se eles ainda querem que você procure o código, pergunte quanto tempo eles gostariam que você gastasse com isso. Lembre-os sutilmente de que você não estará trabalhando no recurso X, no bug Y ou no aprimoramento Z enquanto estiver fazendo isso.
  5. Passe o tempo que eles pedirem. Se você ainda acha que a causa mais provável é o acesso manual ao banco de dados, informe-os.
  6. Se eles ainda querem que você procure o código, aumente o problema, pois isso claramente se tornou um uso improdutivo do tempo da sua equipe.

Você também pode considerar se deve adicionar processos extras para reduzir a probabilidade de acesso manual ao banco de dados, causando esse tipo de problema no futuro.


11
Eu não tinha ideia de que um dos engenheiros fazia uma atualização manual + quase nunca executavam consultas diretamente no banco de dados. Este apenas fez, como uma coisa única e se esqueceu. Passamos um dia + nos preparando para passar uma semana inteira descobrindo o que havia de errado. Minha pergunta é o que acontece se você não conseguir encontrar a causa e não puder sugerir qual a causa potencial.
Nik Kyriakides 25/10

5
"Minha pergunta é o que acontece se você não conseguir encontrar a causa e não puder sugerir qual a causa em potencial". Essa é a razão exata pela qual o sinalizador 'não corrige - não pode duplicar' foi inventado.
Esoterik 25/10/19

4

Eu estava trabalhando na equipe de desenvolvimento de um produto de banco de dados de mainframe quando um cliente relatou que tinha um banco de dados corrompido. Uma corrupção no sentido de que o estado interno dos bits no disco significava que o banco de dados não era legível por meio do software do banco de dados. No mundo do mainframe, os clientes estão pagando US $ milhões e você precisa levar isso a sério. Isto é o que nós fizemos:

Etapa 0: ajude o cliente a voltar a funcionar reparando o banco de dados.

Etapa 1: examinando o arquivo no disco no nível hexadecimal, determinamos que a corrupção era sistemática: havia muitas instâncias da mesma corrupção. Definitivamente, foi causado no nível do software de banco de dados. De fato, era suficientemente sistemático que achamos que podíamos descartar problemas com vários threads.

Depois de eliminar muitas outras teorias, nos deparamos com um utilitário que poderia ser usado para a reorganização física do banco de dados. Parecia ser o único código que tinha acesso aos dados no nível certo. Em seguida, descobrimos uma maneira de executar este utilitário, com opções cuidadosamente selecionadas, que reproduziam o problema. O cliente não foi capaz de confirmar ou negar que isso foi o que eles haviam feito, mas, como era a única explicação que poderíamos apresentar, decidimos que era a causa provável e eles tinham pouca opção a não ser aceitar nosso diagnóstico. .

Etapa 2: Em seguida, fizemos duas alterações no software: (a) dificultamos causar esse efeito acidentalmente por meio de uma interface de usuário "sim, eu sei o que estou fazendo" e (b) introduzimos um novo arquivo de log para que, se se isso acontecesse novamente, teríamos um registro das ações do usuário.

Portanto, basicamente (a) repare os danos e restaure a execução ao vivo, (b) encontre a causa raiz, (c) faça o que for necessário para impedir que isso aconteça novamente ou para permitir um diagnóstico fácil se isso acontecer novamente.


3

Pela minha experiência, o que seu chefe quer é uma garantia de nível de que isso não ocorrerá novamente. Se for o caso que nenhum código foi a causa, porque isso é garantido pelo teste de unidade, portanto, supondo que você já tenha cobertura de teste em sua base de código, a solução deve adicionar "teste" ao seu banco de dados. Vou citar Don Gilman, porque ele pregou lá:

Um banco de dados de produção deve ter registro de acesso completo e controles de acesso baseados em função. Portanto, você deve ter evidências concretas sobre a OMS O QUE QUER QUANDO no banco de dados, deslocando assim a atenção do código para uma segurança operacional ruim.

Além disso, você deve ter o Procedimento operacional padrão para alterar dados na produção. Por exemplo, nenhum DBA deve alterar os dados, nenhum desenvolvedor deve executar a alteração por conta própria e, conforme definido no SOP, deve exigir um do outro formalmente a alteração por correio ou ticket.

Deve haver uma citação como esta em algum lugar; caso contrário, você pode me citar:

Há uma boa razão para os chefs não serem os responsáveis ​​pela limpeza dos banheiros.


1

Há várias coisas que devem ser feitas com bugs não reproduzíveis.

  1. Crie um ticket para ele

Crie um ticket e registre tudo o que você puder imaginar no ticket. Verifique também se esse "bug" já foi registrado antes e vincule os tickets. Eventualmente, você pode obter tickets suficientes para estabelecer um padrão de como reproduzir o bug. Isso inclui soluções alternativas usadas para tentar evitá-lo. Mesmo se essa for a única instância, se houver uma primeira vez, haverá uma segunda vez. Quando você encontrar a causa, feche o ticket com uma explicação de qual foi a causa, para ter uma forte idéia do que aconteceu se isso acontecer novamente (correção perdida em má fusão)

  1. Faça uma análise de proteção

Veja o sistema, o que falhou e como falhou. Tente encontrar áreas do código que possam ser atualizadas para tornar menos provável a falha. Alguns exemplos...

  • Substitua o código ad-hoc por uma chamada dedicada (como execute(<query>)emexecuteMyStoredProcedure(<params>)
  • Execute scripts de verificação noturnos para verificar a integridade dos dados (para que isso possa ser detectado dentro de 24 horas da próxima vez)
  • Adicione / aprimore o log e o arquivamento (backup).
  • Alterar limites de segurança inadequados (por exemplo, pessoas / programas que apenas lêem dados não têm permissão de gravação; não permitindo que desenvolvedores que não são responsáveis ​​pela produção possam fazer logon nos servidores de produção)
  • Adicione verificação / saneamento de dados onde estiver faltando

Isso pode não corrigir o bug, mas mesmo se não o fizer, o sistema agora está mais estável / seguro e ainda compensa.

  1. Adicionar alertas do sistema

Meio que parte de 2, mas algo aconteceu, e você precisa saber quando isso acontece novamente. Você deve criar alguns scripts / programas de verificação de integridade para monitorar o sistema, para que os administradores possam ser alertados dentro de 24 horas após o surgimento do erro (quanto menos atraso, melhor, dentro do motivo). Isso tornará a limpeza muito mais fácil. (Observe que, além dos logs dos bancos de dados, o sistema operacional também deve registrar quem faz login nele e quaisquer ações que não sejam de leitura que eles executam. No mínimo, deve haver logs de tráfego de rede para essa máquina)


0

Seu problema não foi causado por uma falha no seu software, mas por alguém mexendo no banco de dados. Se você chamar as coisas de erradas de "bug", seu bug será facilmente reproduzível: as coisas sempre dão errado quando alguém faz coisas estúpidas no banco de dados. E existem maneiras de evitar esse "bug", não permitindo que o banco de dados seja modificado manualmente ou usando software não testado, e controlando rigorosamente quem pode modificar o banco de dados.

Se você chamar apenas falhas no seu banco de dados de "bug", não terá um erro irreprodutível, não terá nenhum bug. Você pode ter um relatório de bug, mas também possui evidências de que o problema não foi causado por um bug. Portanto, você pode fechar o relatório de erro, não como "irreprodutível", mas algo como "banco de dados danificado". Não é incomum ter relatórios de bugs em que a investigação mostra que não há bugs, mas um usuário usou o software errado, as expectativas do usuário estavam erradas etc.

Nesse caso, você ainda sabe que houve um problema que não deseja que seja repetido; portanto, você executa a mesma ação que no primeiro caso.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.