Trattare con bug non riproducibili

70

Supponiamo che il tuo team scriva un sistema software che sta funzionando bene.

Un giorno uno degli ingegneri esegue erroneamente alcune query SQL che modificano alcuni dati del DB, quindi si dimentica di esso.

Dopo un po 'di tempo scoprite i dati corrotti / errati e tutti si graffiano la testa su quale parte del codice ha causato questo e perché, senza successo. Nel frattempo il project manager insiste sul fatto che troviamo la parte del codice che l'ha provocata.

Come ti occupi di questo?

    
posta Nik Kyriakides 25.10.2018 - 21:39
fonte

9 risposte

130

È ovvio che nessun project manager investirà una quantità infinita di tempo in un tale problema. Vogliono evitare che si ripeta la stessa situazione.

Per raggiungere questo obiettivo, anche se non è possibile trovare la causa principale di tale errore, è spesso possibile prendere alcune misure per

  • Rileva tali errori in precedenza nel caso in cui si ripresentino
  • Rendilo meno probabile che lo stesso errore si verifichi di nuovo
  • Rendi il sistema più robusto contro il tipo specifico di incoerenza

Ad esempio, una registrazione più dettagliata, una gestione degli errori più dettagliata o una segnalazione immediata degli errori potrebbero aiutare a prevenire lo stesso errore di nuovo o trovare la causa principale. Se il tuo sistema consente l'aggiunta di trigger di database, forse è possibile aggiungere un trigger che vieta l'incoerenza introdotta in primo luogo.

Pensa a quale potrebbe essere il tipo appropriato di azione nella tua situazione e suggeriscilo al team; Sono certo che il tuo project manager sarà soddisfatto.

One day one of the engineers mistakenly runs some SQL queries that change some of the DB data, then forgets about it.

Come accennato da altri, è anche una buona idea proibire tale procedura (se si ha influenza su come funziona il sistema). A nessuno dovrebbe essere permesso di eseguire query ad hoc non documentate che cambiano il contenuto del database. Se è necessaria una tale query, assicurarsi che vi sia un criterio per archiviare la query insieme alla data di esecuzione, il nome della persona che l'ha eseguita e il motivo per cui è stata utilizzata, in un luogo documentato.

    
risposta data 25.10.2018 - 22:20
fonte
47

Questo non è un bug

Almeno non sul tuo codice. È un bug nel tuo processo . Il tuo project manager dovrebbe essere molto più preoccupato del tuo processo rispetto al tuo codice.

How do you deal with this?

Semplicemente, non consentendo agli ingegneri di modificare i database di produzione o di sviluppo condiviso .

Supponendo che questo sia un database di sviluppo condiviso:

Idealmente, se possibile, evitare di avere un database condiviso in primo luogo . Invece, avere database per sviluppatori che sono di breve durata. Questo dovrebbe essere automatizzato con script, altrimenti il costo per il test diventa troppo grande, e c'è un incentivo a non testare le cose. Puoi avere questi database sulla workstation dello sviluppatore o su un server centrale.

Se, per qualche ragione, DEVI assolutamente avere un database condiviso, dovresti utilizzare dispositivi - in sostanza, qualcosa che imposta il database in uno stato noto buono ogni volta che è necessario utilizzarlo. Ciò evita che gli sviluppatori vengano morsi dai cambiamenti di altre persone.

Se devi applicare modifiche permanenti al database, devi impegnarle sul controllo del codice sorgente . Imposta il tuo database in modo tale che gli sviluppatori non abbiano il permesso di scrivere direttamente su di esso e abbiano un programma che estrae le modifiche dal controllo del codice sorgente e le applichi.

Infine, dalla tua descrizione su come stai eseguendo il debug delle cose, sembra che tu non stia utilizzando CI . Utilizza CI . È un po 'difficile da configurare, ma a lungo andare si risparmia molto tempo, senza contare che non ti preoccupi di bug di database non riproducibili. Dovrai solo preoccuparti di heisenbugs adesso!

Supponendo che questo sia un database di produzione:

Se i tuoi sviluppatori stanno cambiando i database di produzione, molte cose sono andate terribilmente male, anche se le modifiche sono assolutamente corrette.

Gli sviluppatori non dovrebbero mai accedere ai database di produzione . Non c'è assolutamente alcun motivo per, e così tante cose che possono andare molto molto sbagliate.

Se hai bisogno di correggere qualcosa in un database di produzione, prima fai il backup, ripristina quel backup su un'istanza diversa (sviluppo) e allora giocare attorno a quel database di sviluppo. Una volta che pensi di avere una soluzione pronta (sul controllo del codice sorgente!), Devi rifare il ripristino, applicare la correzione e vedere il risultato. Quindi, dopo aver ripristinato le cose (e prevenendo idealmente gli aggiornamenti simultanei), correggi l'istanza di produzione, idealmente attraverso una patch software.

Se hai bisogno di test qualcosa in un database di produzione ... no, non lo fai. Qualunque sia il test che devi fare, dovresti farlo in un'istanza di sviluppo. Se hai bisogno di alcuni dati per eseguire i test, ottieni quei dati lì dentro.

    
risposta data 26.10.2018 - 02:43
fonte
13

Un database di produzione deve disporre di una registrazione di accesso completo e di controlli di accesso basati sui ruoli. Quindi dovresti avere prove concrete su CHI ha fatto COSA QUANDO al database spostando così l'attenzione dal codice alla scarsa sicurezza operativa.

    
risposta data 25.10.2018 - 22:48
fonte
6

In questo caso, alla fine hai scoperto la causa, ma hai ipotizzato che non avevi ...

In primo luogo, analizza cosa è cambiato. Se il sistema stava funzionando bene prima, un'attenta analisi di tutto ciò che è stato fatto di recente potrebbe rivelare la modifica che ha causato il bug. Rivedere sistematicamente il controllo della versione, l'IC / i sistemi di implementazione e il controllo di configurazione per vedere se qualcosa è cambiato. Esegui git bisect o un meccanismo equivalente per eseguire una ricerca binaria. Controlla i registri. Cerca i log che non sapevi di avere. Parla con tutti con l'accesso al sistema per vedere se hanno fatto qualcosa di recente. Per il tuo problema, se sei abbastanza approfondito in questo processo, questo dovrebbe rivelarsi, auspicabilmente, le query SQL dimenticate.

Secondo, strumentazione. Se non riesci a trovare direttamente la causa di un bug, aggiungi la strumentazione che lo circonda per raccogliere dati sul problema. Chiedetevi "se potessi riprodurre questo bug su comando, cosa dovrei vedere nel debugger", e quindi registrarlo. Ripeti secondo necessità fino a quando non avrai una migliore comprensione del problema. Come suggerisce Doc Brown, aggiungi la registrazione per gli stati rilevanti per il bug. Aggiungi asserzioni che rilevano dati corrotti. Ad esempio, se il tuo bug è un arresto anomalo dell'applicazione, aggiungi un meccanismo di registrazione degli arresti anomali. Se ne hai già uno, ottimo, aggiungi annotazioni ai registri degli arresti anomali per registrare lo stato potenzialmente rilevante per l'arresto anomalo. Valuta se possono essere coinvolti problemi di concorrenza e test per l'esercizio della sicurezza dei thread .

Terzo, resilienza. I bug sono inevitabili, quindi chiediti come puoi migliorare i tuoi sistemi per essere più resilienti, in modo che il recupero dall'errore sia più facile. I tuoi backup potrebbero essere migliorati (o esistenti)? Monitoraggio, failover e allerta migliori? Più ridondanza? Migliore gestione degli errori? Separare i servizi dipendenti l'uno dall'altro? Puoi migliorare i tuoi processi relativi all'accesso al database e alle query manuali? Nella migliore delle ipotesi, queste cose renderanno le conseguenze del tuo bug meno gravi e, nel peggiore dei casi, probabilmente saranno comunque buone cose da fare.

    
risposta data 26.10.2018 - 09:33
fonte
4
  1. Spiega al tuo project manager che ritieni che la causa più probabile sia l'accesso al database manuale.
  2. Se vogliono ancora che tu cerchi il codice che ha causato questo, vai a dare un altro sguardo al codice.
  3. Torna tra un paio d'ore (o un altro momento appropriato) e di 'che non riesci a trovare alcun codice che possa averlo causato, quindi ritieni che la causa più probabile sia l'accesso al database manuale.
  4. Se loro ancora vogliono che tu cerchi il codice, chiedi quanto tempo vorresti che spendessi su questo. Ricorda loro che non lavorerai su feature X, bug Y o enhancement Z mentre stai facendo questo.
  5. Trascorri tutto il tempo che ti chiedono. Se pensi ancora che la causa più probabile sia l'accesso al database manuale, diglielo.
  6. Se loro ancora vogliono che tu cerchi il codice, intensifica il problema poiché questo è chiaramente diventato un uso improduttivo del tempo della tua squadra.

Potresti anche prendere in considerazione l'eventualità di aggiungere processi aggiuntivi per ridurre la probabilità che l'accesso al database manuale causi questo tipo di problema in futuro.

    
risposta data 25.10.2018 - 22:04
fonte
3

Dalla mia esperienza, ciò che il tuo capo desidera è una certa garanzia che questo non si ripresenterà. Se è il caso che nessun codice è stato la causa, perché ciò è assicurato dal test dell'unità, quindi supponendo che abbiate già una copertura di test sul vostro codice base, la soluzione dovrebbe aggiungere "test" al vostro database. Citerò Don Gilman, perché l'ha inchiodato lì:

A production database should have full access logging and role based access controls. Thus you should have hard evidence as to WHO did WHAT WHEN to the database thus moving the attention from the code to poor operational security.

Inoltre, dovresti disporre della Procedura operativa standard sulla modifica dei dati in produzione. Ad esempio, nessun DBA dovrebbe modificare i dati, nessuno sviluppatore dovrebbe eseguire la modifica da sé e dovrebbe, come definito nel SOP, richiedere reciprocamente formalmente la modifica per posta o ticket.

Ci deve essere una citazione come questa da qualche parte, se non puoi citarmi sopra:

There is a perfectly good reason for chefs not being the ones responsible for cleaning toilets.

    
risposta data 26.10.2018 - 02:47
fonte
2

Stavo lavorando al team di sviluppo per un prodotto di database mainframe quando un cliente ha segnalato di avere un database corrotto. Una corruzione nel senso che lo stato interno dei bit sul disco significava che il database non era leggibile tramite il software del database. Nel mondo mainframe i clienti ti pagano $ milioni e devi prenderlo sul serio. Questo è ciò che abbiamo fatto:

Passaggio 0: aiutare il cliente a tornare operativo e in esecuzione riparando il database.

Passaggio 1: esaminando il file sul disco a livello hex abbiamo determinato che la corruzione era sistematica: c'erano molti casi della stessa corruzione. Quindi è stato sicuramente causato a livello del software del database. In effetti, è stato sufficientemente sistematico che abbiamo ritenuto di poter escludere problemi di multi-threading.

Dopo aver eliminato molte altre teorie in cui ci siamo imbattuti in un'utilità che potrebbe essere utilizzata per la riorganizzazione fisica del database. Sembrava essere l'unico codice che aveva accesso ai dati al giusto livello. Abbiamo quindi scoperto un modo di eseguire questa utility, con opzioni accuratamente selezionate, che riproducevano il problema. Il cliente non è stato in grado di confermare o negare che questo fosse ciò che avevano fatto, ma poiché era l'unica spiegazione che avremmo potuto trovare, abbiamo deciso che era la causa probabile e non avevano altra scelta che accettare la nostra diagnosi .

Passaggio 2: Abbiamo quindi apportato due modifiche al software: (a) reso più difficile provocare questo effetto accidentalmente attraverso un'interfaccia utente "sì, so cosa sto facendo" e (b) introducendo un nuovo file di registro in modo che se dovesse accadere di nuovo, avremmo una registrazione delle azioni dell'utente.

Quindi fondamentalmente (a) riparare il danno e ripristinare l'esecuzione in tempo reale, (b) trovare la causa principale, (c) fare tutto il necessario per evitare che accada di nuovo, o per consentire una facile diagnosi se si ripresenta.

    
risposta data 29.10.2018 - 15:54
fonte
1

Ci sono molte cose che devono essere fatte con bug non riproducibili.

  1. Crea un ticket per questo

Crea un ticket e registra tutto ciò che puoi pensare nel ticket. Controlla anche se questo "bug" è stato registrato prima e collega i biglietti insieme. Alla fine potresti ottenere abbastanza biglietti per stabilire un modello per come riprodurre il bug. Questo include il lavoro in giro usato per cercare di evitarlo. Anche se questa è l'unica istanza, se c'è una prima volta, ci sarà alla fine una seconda volta. Quando trovi la causa, chiudi il ticket con una spiegazione di quale sia la causa, in modo da avere una chiara idea di cosa è successo se si verifica nuovamente (correzione persa in caso di unione errata)

  1. Effettua un'analisi duratura

Guarda il sistema, cosa è fallito e come ha fallito. Prova a trovare le aree del codice che possono essere aggiornate per rendere meno probabile l'errore. Alcuni esempi ...

  • Sostituisci il codice ad hoc con una chiamata dedicata (come execute(<query>) con executeMyStoredProcedure(<params>)
  • Esegui script di verifica notturna per verificare l'integrità dei dati (in modo che questo possa essere rilevato entro 24 ore la prossima volta)
  • Aggiungi / migliora la registrazione e l'archiviazione (backup)
  • Modifica dei limiti di sicurezza impropri (ad esempio, le persone / i programmi che leggono solo i dati non hanno il permesso di scrittura; non permettendo agli sviluppatori che non sono responsabili della produzione di accedere ai server di produzione)
  • Aggiungi verifica dati / servizi igienico-sanitari dove manca

Questo potrebbe non correggere il bug, ma anche se non lo fosse, il sistema ora è più stabile / sicuro, quindi continua a essere redditizio.

  1. Aggiungi avvisi di sistema

Una parte del 2, ma qualcosa è successo, e devi sapere quando succede di nuovo. Dovresti creare alcuni script / programmi di controllo dello stato per monitorare il sistema, in modo che gli amministratori possano essere avvisati entro 24 ore dal resurfacing dei bug (meno ritardo, meglio, entro limiti ragionevoli). Questo renderà la pulizia molto più facile. (Si noti che oltre ai log del database, il sistema operativo deve anche registrare chi esegue il login e tutte le azioni non di lettura che eseguono. Per lo meno, dovrebbero esserci registri di traffico di rete su quella macchina)

    
risposta data 26.10.2018 - 23:01
fonte
0

Il tuo problema non è stato causato da un errore nel tuo software, ma da qualcuno che ha manipolato il database. Se definisci un errore un "bug", allora il tuo bug è facilmente riproducibile: le cose andranno sempre male quando qualcuno fa cose stupide al database. E ci sono modi per evitare questo "bug", non permettendo che il database sia modificato manualmente o usando software non testato, e controllando rigorosamente chi può modificare il database.

Se chiami solo errori nel tuo database come un "bug", allora non hai un bug irreprodabile, non hai alcun bug. Potresti avere un bug report, ma hai anche la prova che il problema non è stato causato da un bug. Quindi puoi chiudere il bug report, non come "irriproducibile", ma qualcos'altro come "database danneggiato". Non è raro avere segnalazioni di bug in cui l'investigazione mostra che non ci sono bug, ma un utente ha usato il software sbagliato, le aspettative dell'utente erano sbagliate ecc.

In questo caso, si sa ancora che c'era un problema che non si desidera ripetere, quindi si esegue la stessa azione del primo caso.

    
risposta data 27.10.2018 - 10:26
fonte

Leggi altre domande sui tag