Radzenie sobie z niepowtarzalnymi błędami

73

Załóżmy, że Twój zespół pisze system, który działa (dość zaskakująco!).

Pewnego dnia jeden z inżynierów omyłkowo uruchamia niektóre zapytania SQL, które zmieniają niektóre dane DB, a następnie zapomina o tym.

Po pewnym czasie odkrywasz uszkodzone / błędne dane i wszyscy drapią się w głowie, która część kodu to spowodowała i dlaczego, bezskutecznie. Tymczasem kierownik projektu nalega, aby znaleźć część kodu, która go spowodowała.

Jak sobie z tym radzisz?

Nik Kyriakides
źródło
32
Jeśli inżynier o tym zapomniał, skąd wiesz, że tak się stało? Jak to się stało, że został uszkodzony przez osobę uruchamiającą skrypt, a nie przez błąd?
DaveG
18
Miał objawienie po dniu lub dwóch. Jest to hipotetyczne, na wypadek, gdyby nigdy nie pamiętał, co mogło mieć miejsce.
Nik Kyriakides,
12
To jest hipotetyczne. Jestem pewien, że premier kazałby nam ścigać to tyle, ile możemy, gdyby nigdy nie pamiętał. Wiem, że bym to zrobił.
Nik Kyriakides,
59
xkcd.com/583 ;) [język NSFW]
Baldrickk
100
„Załóżmy, że Twój zespół pisze dobrze działający system oprogramowania.” Przestań dokuczać mi niemożliwymi fantazjami!
Paul D. Waite,

Odpowiedzi:

134

Jest oczywiste, że żaden kierownik projektu nie zainwestuje nieskończenie wiele czasu w taki problem. Chcą zapobiec powtórzeniu się tej samej sytuacji.

Aby osiągnąć ten cel, nawet jeśli nie można znaleźć podstawowej przyczyny takiej awarii, często można podjąć pewne kroki

  • Wykrywaj takie awarie wcześniej, na wypadek ich ponownego wystąpienia
  • Zmniejsz prawdopodobieństwo, że ta sama awaria się powtórzy
  • Uczyń system bardziej odpornym na określony rodzaj niespójności

Na przykład bardziej szczegółowe rejestrowanie, bardziej szczegółowa obsługa błędów lub natychmiastowa sygnalizacja błędów może pomóc w zapobieganiu ponownemu pojawieniu się tego samego błędu lub w znalezieniu głównej przyczyny. Jeśli twój system pozwala na dodawanie wyzwalaczy bazy danych, być może możliwe jest dodanie wyzwalacza, który w pierwszej kolejności zabrania wprowadzania niespójności.

Zastanów się, jakie działania mogą być odpowiednie w twojej sytuacji i zasugeruj to zespołowi; Jestem pewien, że twój kierownik projektu będzie zadowolony.

Pewnego dnia jeden z inżynierów omyłkowo uruchamia niektóre zapytania SQL, które zmieniają niektóre dane DB, a następnie zapomina o tym.

Jak wspomnieli inni, dobrym pomysłem jest również zakazanie takiej procedury (jeśli masz wpływ na sposób działania systemu). Nikomu nie powinno się zezwalać na uruchamianie nieudokumentowanych zapytań ad-hoc, które zmieniają zawartość bazy danych. Jeśli zachodzi potrzeba takiego zapytania, upewnij się, że istnieje polityka przechowywania zapytania wraz z datą jego wykonania, nazwą osoby, która je wykonała oraz powodem, dla którego zostało użyte, w udokumentowanym miejscu.

Doktor Brown
źródło
8
@NicholasKyriakides Prawdopodobnie oba. Wszystkie są zdroworozsądkowymi środkami upraszczającymi debugowanie odroczone. Prawdopodobnie zostały napisane w niezliczonych procedurach.
Nic Hartley,
29
Od czasu do czasu zdarza się, że masz jakiś poważny problem w systemie produkcyjnym i mimo znacznego wysiłku nie możesz ustalić przyczyny. Ostatecznie przypisujesz to promieniom kosmicznym i próbujesz poprawić raportowanie (więc jeśli to się powtórzy, będziesz mieć większą szansę na znalezienie przyczyny) i złagodzenie (więc jeśli to się powtórzy, obrażenia będą minimalne) i sprawdź, czy to powtarza się
David Schwartz
2
@Nicholas Kyriakides: osobiste doświadczenie przez kilka dziesięcioleci.
Doc Brown
4
Należy również zauważyć, że jest bardzo możliwe, że nawet jeśli wystąpił błąd, może już nie być. Najlepsze, co możesz czasem zrobić, to naprawić dane i ulepszyć testy / procedury, aby upewnić się, że ten sam problem się nie powtórzy.
kutschkem
2
Znajdowanie sporadycznych problemów polega na rejestrowaniu i znajdowaniu dławika, który może je wykryć, gdy wystąpią, a następnie chodzenie stamtąd do tyłu, aby wskazać źródło. Czasami wymaga to nieprzyjemnych rzeczy, takich jak wyzwalacze lub wdrażanie kodu z hałaśliwym rejestrowaniem błędów, aby uzyskać kontrolę nad czasem i miejscem wystąpienia błędu.
AaronLS,
51

To nie jest błąd

Przynajmniej nie w twoim kodzie. To błąd w twoim procesie . Kierownik projektu powinien bardziej martwić się procesem niż kodem.

Jak sobie z tym radzisz?

Po prostu, nie pozwalając inżynierom zmieniać produkcji lub współużytkowanych baz danych programowania .


Zakładając, że jest to wspólna baza danych programowania:

Najlepiej, jeśli to w ogóle możliwe, przede wszystkim unikaj posiadania wspólnej bazy danych . Zamiast tego mają krótkotrwałe bazy danych dla programistów. Powinno to zostać zautomatyzowane za pomocą skryptów, w przeciwnym razie koszt testowania stanie się zbyt duży, a zachęta do nie testowania rzeczy. Możesz mieć te bazy danych na stacji roboczej dewelopera lub na centralnym serwerze.

Jeśli z jakiegoś powodu absolutnie MUSISZ mieć współużytkowaną bazę danych, powinieneś używać urządzeń - w zasadzie czegoś, co ustawia bazę danych w dobrze znany stan za każdym razem, gdy musisz z niej korzystać. Zapobiega to ugryzieniu programistów przez zmiany innych osób.

Jeśli chcesz zastosować trwałe zmiany w bazie danych, powinieneś je zatwierdzić pod kontrolą źródła . Skonfiguruj bazę danych w taki sposób, aby deweloperzy nie mieli uprawnień do pisania bezpośrednio do niej, i mieć program, który pobiera zmiany z kontroli źródła i stosuje je.

Wreszcie z opisu sposobu debugowania rzeczy wynika, że ​​nie używasz CI . Użyj CI . Jest to trochę kłopotliwe w konfiguracji, ale na dłuższą metę pozwoli zaoszczędzić TAK dużo czasu, nie wspominając już o powstrzymaniu cię od martwienia się o nie powtarzalne błędy bazy danych. Teraz będziesz musiał się tylko martwić o heisenbugs !


Zakładając, że jest to produkcyjna baza danych:

Jeśli twoi twórcy zmieniają produkcyjne bazy danych, wiele rzeczy poszło strasznie źle, nawet jeśli zmiany są absolutnie poprawne.

Programiści nigdy nie powinni uzyskiwać dostępu do baz danych produkcji . Nie ma absolutnie żadnego powodu, a tak wiele rzeczy może pójść bardzo źle.

Jeśli chcesz naprawić coś w produkcyjnej bazie danych, najpierw wykonaj kopię zapasową, przywróć tę kopię zapasową w innej instancji (programistycznej), a następnie obejrzyj tę programistyczną bazę danych. Gdy uważasz, że masz gotową poprawkę (na kontroli źródła!), Ponownie wykonaj przywracanie, zastosuj poprawkę i zobacz wynik. Następnie, po ponownym utworzeniu kopii zapasowej (i idealnie zapobiegając jednoczesnym aktualizacjom), naprawiasz instancję produkcyjną, najlepiej za pomocą poprawki oprogramowania.

Jeśli musisz coś przetestować w produkcyjnej bazie danych ... nie, nie musisz. Niezależnie od tego, jakie testy musisz wykonać, powinieneś je wykonać w instancji programistycznej. Jeśli potrzebujesz danych do przeprowadzenia testów, znajdziesz je tam.

goncalopp
źródło
12
Więc twoim zalecanym rozwiązaniem jest podróż w czasie?
Benubird
7
Chociaż jest to przyzwoite rozwiązanie dla podanego przykładu, pytanie ma znacznie bardziej ogólny kontekst radzenia sobie z błędami, których nie można odtworzyć, oraz menedżerami, którzy chcą, aby je uporali. Może to dotyczyć znacznie więcej niż tylko problemów z bazą danych i zarządzania uprawnieniami. Wydaje mi się, że ta odpowiedź w rzeczywistości nie odpowiada zamierzonemu pytaniu, tylko podanemu przykładowi.
Kyle Wardle
@KyleWardle wyraził zgodę. Myślę, że odpowiedź Doc Browna dość dobrze obejmuje ogólny przypadek (szczegółowe rejestrowanie i obsługa błędów, warunki bezpieczeństwa). Najczęściej dodawałem moje, ponieważ nie widziałem, żeby nikt nie wspominał o niepowodzeniach procesu, które doprowadziły do ​​problemu w pierwszej kolejności
goncalopp
2
@Benubird Myślę, że odpowiedź sprowadza się do „sposób, w jaki sobie z tym radzisz, zapobiega ponownemu wystąpieniu problemu”. Nie sądzę, że można „rozwiązać” uszkodzoną produkcyjną bazę danych z perspektywy inżynierii oprogramowania.
goncalopp
1
Nie zamierzasz zmieniać kodu, aby umieścić dane w bazie danych deweloperów. Wszędzie, gdzie pracowałem, w tym duże korporacje, programiści mogą swobodnie wstawiać dane testowe i korzystać z tych samych poświadczeń, których używa aplikacja.
David Conrad
13

Produkcyjna baza danych powinna mieć rejestrowanie pełnego dostępu i kontrolę dostępu opartą na rolach. Dlatego powinieneś mieć twarde dowody na to, kto KTO zrobił KIEDY w bazie danych, przenosząc tym samym uwagę z kodu na słabe bezpieczeństwo operacyjne.

Don Gilman
źródło
2
Wygląda na to, że mogą nie wiedzieć dokładnie, kiedy nastąpiło uszkodzenie danych, co może utrudnić ustalenie, które dzienniki muszą zbadać.
Natanael,
3
Niestety podczas śledzenia jednego z nich odkryliśmy, że niszczy on również dzienniki. (Tak, to. Błąd był prawdziwy.)
Joshua
Połączenie rejestrowania z zaplanowanymi zadaniami sprawdzającymi integralność danych, nawet jeśli tylko przez noc, oznacza, że ​​problemy mogą być oznaczane wcześniej i rozwiązane. Jeśli chcesz być naprawdę ostrożny, poproś o sprawdzenie zmian.
Keith,
Wszędzie, gdzie pracowałem, deweloperzy łączą się z bazą danych przy użyciu tych samych poświadczeń, których używa aplikacja, więc rejestrowanie dostępu pokazywałoby tylko, gdy ten identyfikator wprowadził zmianę, a nie to, że zrobił to człowiek, a nie program. Podejrzewam, że można porównać znacznik czasu z dziennikami aplikacji, aby sprawdzić, czy aplikacja robi coś, co w tym czasie zapisałoby się do bazy danych.
David Conrad
@DavidConrad: Dlaczego deweloperzy mają dostęp do poświadczeń używanych przez aplikację w produkcji? Powinieneś używać pewnego rodzaju tajnego zarządzania, aby te poświadczenia nie mogły być odczytane, z wyjątkiem konta usługi aplikacji z serwerów produkcyjnych.
Daniel Pryden
6

W tym przypadku ostatecznie ustaliłeś przyczynę, ale przyjmując hipotezę, że nie ...

Najpierw przeanalizuj, co się zmieniło. Jeśli system działał wcześniej dobrze, uważne spojrzenie na wszystko, co zostało ostatnio zrobione, może ujawnić zmianę, która spowodowała błąd. Systematycznie przeglądaj kontrolę wersji, systemy CI / wdrażania i kontrolę konfiguracji, aby sprawdzić, czy coś się zmieniło. Uruchom git bisect lub równoważny mechanizm, aby przeprowadzić wyszukiwanie binarne. Sprawdź dzienniki. Poszukaj dzienników, o których nie wiedziałeś, że masz. Porozmawiaj ze wszystkimi, którzy mają dostęp do systemu, aby sprawdzić, czy coś ostatnio zrobili. Jeśli chodzi o twój problem, jeśli jesteś wystarczająco dokładny w tym procesie, mam nadzieję, że powinno to ujawnić zapomniane zapytania SQL.

Po drugie, oprzyrządowanie. Jeśli nie możesz bezpośrednio znaleźć przyczyny błędu, dodaj wokół niego oprzyrządowanie, aby zebrać dane o problemie. Zadaj sobie pytanie „czy mógłbym odtworzyć ten błąd na polecenie, na co chciałbym spojrzeć w debuggerze”, a następnie zaloguj się. Powtarzaj w razie potrzeby, aż lepiej zrozumiesz problem. Jak sugeruje Doc Brown, dodaj rejestrowanie dla stanów związanych z błędem. Dodaj asercje, które wykrywają uszkodzone dane. Na przykład, jeśli błąd jest awarią aplikacji, dodaj mechanizm rejestrowania awarii. Jeśli masz już jeden, świetnie, dodaj adnotacje do dzienników awarii, aby zapisać stan potencjalnie istotny dla awarii. Zastanów się, czy mogą wystąpić problemy z współbieżnością, i przetestuj, aby sprawdzić bezpieczeństwo wątków .

Po trzecie, odporność. Błędy są nieuniknione, więc zadaj sobie pytanie, w jaki sposób możesz ulepszyć swój system, aby był bardziej odporny, aby łatwiej było odzyskać system po błędzie. Czy twoje kopie zapasowe mogą zostać ulepszone (lub istnieją)? Lepsze monitorowanie, przełączanie awaryjne i alarmowanie? Więcej redundancji? Lepsza obsługa błędów? Oddzielić od siebie usługi zależne? Czy możesz usprawnić swoje procesy związane z dostępem do bazy danych i ręcznymi zapytaniami? W najlepszym wypadku te rzeczy sprawią, że konsekwencje twojego błędu będą mniej dotkliwe, aw najgorszym razie prawdopodobnie są to dobre rzeczy do zrobienia.

Zach Lipton
źródło
5
  1. Wyjaśnij swojemu kierownikowi projektu, że Twoim zdaniem najbardziej prawdopodobną przyczyną jest ręczny dostęp do bazy danych.
  2. Jeśli nadal chcą, abyś poszukał kodu, który to spowodował, przejdź do kodu.
  3. Wróć za kilka godzin (lub w innym odpowiednim czasie) i powiedz, że nie możesz znaleźć kodu, który by to spowodował, dlatego nadal uważasz, że najbardziej prawdopodobną przyczyną jest ręczny dostęp do bazy danych.
  4. Jeśli nadal chcą, abyś poszukał kodu, zapytaj, ile czasu chcieliby na to poświęcić. Subtelnie przypomnij im, że podczas pracy nie będziesz pracował nad funkcją X, błędem Y lub ulepszeniem Z.
  5. Poświęć tyle czasu, ile poprosą. Jeśli nadal uważasz, że najbardziej prawdopodobną przyczyną jest ręczny dostęp do bazy danych, powiedz im o tym.
  6. Jeśli nadal chcą, abyś szukał kodu, eskaluj problem, ponieważ najwyraźniej stało się to nieproduktywnym wykorzystaniem czasu twojego zespołu.

Możesz również rozważyć, czy powinieneś dodać dodatkowe procesy, aby zmniejszyć prawdopodobieństwo ręcznego dostępu do bazy danych powodującego tego rodzaju problemy w przyszłości.

Philip Kendall
źródło
1
Nie miałem pojęcia, że ​​jeden z inżynierów dokonał ręcznej aktualizacji + inżynierowie prawie nigdy nie uruchamiają zapytań bezpośrednio w bazie danych. Ten po prostu zrobił to jednorazowo i zapomniał o tym. Spędziliśmy dzień + przygotowując się do spędzenia pełnego tygodnia na ustaleniu, co jest nie tak. Moje pytanie brzmi, co się stanie, jeśli nie możesz znaleźć przyczyny i nie możesz zasugerować, jaka może być potencjalna przyczyna.
Nik Kyriakides,
5
„Moje pytanie dotyczy tego, co się stanie, jeśli nie możesz znaleźć przyczyny i nie możesz zasugerować, jaka może być potencjalna przyczyna”. Właśnie z tego powodu wymyślono flagę „nie można naprawić - nie można powielić”.
esoterik
4

Pracowałem w zespole programistów nad bazą danych na komputerze mainframe, gdy klient zgłosił, że ma uszkodzoną bazę danych. Zniszczenie w tym sensie, że wewnętrzny stan bitów na dysku spowodował, że baza danych nie była czytelna za pomocą oprogramowania bazy danych. W świecie komputerów mainframe klienci płacą ci miliony dolarów i musisz wziąć to na poważnie. Oto co zrobiliśmy:

Krok 0: pomóż klientowi ponownie uruchomić i naprawić, naprawiając bazę danych.

Krok 1: badając plik na dysku na poziomie heksadecymalnym, ustaliliśmy, że uszkodzenie było systematyczne: było wiele przypadków tego samego uszkodzenia. Zdecydowanie zostało to spowodowane na poziomie oprogramowania bazy danych. Rzeczywiście, było wystarczająco systematyczne, że uważaliśmy, że możemy wykluczyć problemy z wielowątkowością.

Po wyeliminowaniu wielu innych teorii stworzyliśmy narzędzie, które można wykorzystać do fizycznej reorganizacji bazy danych. Wydawało się, że to jedyny kod, który miał dostęp do danych na odpowiednim poziomie. Następnie odkryliśmy sposób uruchamiania tego narzędzia ze starannie dobranymi opcjami, które odtworzyły problem. Klient nie był w stanie potwierdzić ani zaprzeczyć, że to właśnie zrobili, ale ponieważ było to jedyne wyjaśnienie, jakie mogliśmy wymyślić, zdecydowaliśmy, że to prawdopodobna przyczyna, i nie mieli wyboru, jak zaakceptować naszą diagnozę .

Krok 2: Następnie wprowadziliśmy dwie zmiany w oprogramowaniu: (a) utrudniłem przypadkowe wywołanie tego efektu za pomocą interfejsu użytkownika „tak wiem, co robię”, oraz (b) wprowadzenie nowego pliku dziennika, aby jeśli to się powtórzyło, mielibyśmy zapis działań użytkownika.

Więc w zasadzie (a) napraw szkody i przywróć bieżące działanie, (b) znajdź pierwotną przyczynę, (c) zrób wszystko, co konieczne, aby zapobiec powtórzeniu się lub umożliwić łatwą diagnozę, jeśli to się powtórzy.

Michael Kay
źródło
3

Z mojego doświadczenia wynika, że ​​twój szef chce mieć pewność, że to się nie powtórzy. Jeśli jest tak, że przyczyną nie jest żaden kod, ponieważ zapewnia to testowanie jedności, więc zakładając, że masz już zasięg testowy na bazie kodu, rozwiązaniem powinno być dodanie „testowania” do bazy danych. Zacytuję Dona Gilmana, bo on tam przybił:

Produkcyjna baza danych powinna mieć rejestrowanie pełnego dostępu i kontrolę dostępu opartą na rolach. Dlatego powinieneś mieć twarde dowody na to, kto KTO zrobił KIEDY w bazie danych, przenosząc tym samym uwagę z kodu na słabe bezpieczeństwo operacyjne.

Ale także powinieneś mieć Standardową Procedurę Operacyjną dotyczącą zmiany danych w produkcji. Na przykład żaden DBA nie powinien zmieniać danych, żaden programista nie powinien sam wykonywać zmian i powinni, zgodnie z definicją w SOP, wymagać od siebie formalnej zmiany pocztą lub biletem.

Musi być gdzieś taki cytat, jeśli nie, możesz zacytować mnie na ten temat:

Jest zupełnie dobry powód, dla którego szefowie kuchni nie są odpowiedzialni za czyszczenie toalet.

CesarScur
źródło
1

Jest kilka rzeczy, które należy zrobić z błędami, których nie można odtworzyć.

  1. Utwórz bilet na to

Utwórz bilet i zaloguj wszystko, co możesz wymyślić na bilecie. Sprawdź także, czy ten „błąd” był wcześniej rejestrowany, i połącz ze sobą bilety. W końcu możesz otrzymać wystarczającą liczbę biletów, aby ustalić wzór odtworzenia błędu. Obejmuje to obejścia stosowane w celu uniknięcia tego. Nawet jeśli jest to jedyny przypadek, jeśli nastąpi po raz pierwszy, w końcu nastąpi drugi raz. Kiedy znajdziesz przyczynę, zamknij zgłoszenie z wyjaśnieniem przyczyny, aby mieć dobre pojęcie o tym, co się stanie, jeśli to się powtórzy (poprawka utracona w wyniku błędnego scalenia)

  1. Wykonaj analizę hartowania

Spójrz na system, co się nie udało i jak się nie udało. Spróbuj znaleźć obszary kodu, które można zaktualizować, aby zmniejszyć prawdopodobieństwo awarii. Kilka przykładów...

  • Zamień kod ad-hoc na dedykowane połączenie (np. execute(<query>)ZexecuteMyStoredProcedure(<params>)
  • Uruchom nocne skrypty weryfikacyjne, aby zweryfikować integralność danych (aby można je było wykryć w ciągu najbliższych 24 godzin)
  • Dodaj / popraw rejestrowanie i archiwizację (tworzenie kopii zapasowych).
  • Zmień niewłaściwe limity bezpieczeństwa (na przykład osoby / programy, które tylko czytają dane, nie mają uprawnień do zapisu; Nie zezwalając programistom, którzy nie są odpowiedzialni za produkcję, na logowanie się do serwerów produkcyjnych)
  • Dodaj weryfikację danych / warunki sanitarne, jeśli ich brakuje

Może to nie naprawić błędu, ale nawet jeśli nie, system jest teraz bardziej stabilny / bezpieczny, więc nadal się opłaca.

  1. Dodaj alerty systemowe

To trochę część 2, ale coś się wydarzyło i musisz wiedzieć, kiedy to się powtórzy. Powinieneś utworzyć kilka skryptów / programów sprawdzających kondycję, aby monitorować system, aby administratorzy mogli być powiadamiani w ciągu 24 godzin od ponownego pojawienia się błędu (im mniejsze opóźnienie, tym lepiej, z uzasadnionego powodu). Ułatwi to czyszczenie. (Należy pamiętać, że oprócz dzienników baz danych system operacyjny powinien także rejestrować, kto się do niego loguje, oraz wszelkie wykonywane przez nich działania niezwiązane z czytaniem. Przynajmniej powinny istnieć dzienniki sieciowe ruchu do tego komputera)

Tezra
źródło
0

Twój problem nie był spowodowany błędem w oprogramowaniu, ale przez kogoś majstrującego przy bazie danych. Jeśli nazwiesz coś złego, „błędem”, wtedy twój błąd będzie łatwo powtarzalny: zawsze coś pójdzie nie tak, gdy ktoś zrobi głupie rzeczy w bazie danych. Są też sposoby na uniknięcie tego „błędu” poprzez niedopuszczenie do ręcznej modyfikacji bazy danych lub użycie niesprawdzonego oprogramowania oraz ścisłą kontrolę nad tym, kto może modyfikować bazę danych.

Jeśli nazywasz tylko usterki w bazie danych „błędem”, to nie masz nieodwracalnego błędu, w ogóle go nie ma. Możesz mieć raport o błędzie, ale masz również dowody, że problem nie został spowodowany przez błąd. Możesz więc zamknąć raport o błędzie, nie jako „nieodwracalny”, ale coś innego jak „uszkodzona baza danych”. Często zdarza się, że raporty o błędach, w których dochodzenie wykazuje, że nie ma błędu, ale użytkownik źle używał oprogramowania, oczekiwania użytkownika były błędne itp.

W takim przypadku nadal wiesz, że wystąpił problem, którego nie chcesz powtarzać, więc podejmij takie same działania, jak w pierwszym przypadku.

gnasher729
źródło