Работа с невоспроизводимыми ошибками

73

Предположим, ваша команда пишет программную систему, которая (что удивительно!) Работает нормально.

Однажды один из инженеров по ошибке запускает некоторые SQL-запросы, которые изменяют некоторые данные БД, а затем забывает об этом.

Через некоторое время вы обнаруживаете испорченные / ошибочные данные, и все ломают голову над тем, какая часть кода вызывала это и почему, но безрезультатно. Между тем руководитель проекта настаивает на том, чтобы мы нашли ту часть кода, которая его вызвала.

Как вы справляетесь с этим?

Ник Кириакидес
источник
32
Если инженер забыл об этом, как вы узнали, что это случилось? Как вам это испортил кто-то запускающий скрипт, а не ошибка?
DaveG
18
У него было прозрение через день или два. Это гипотетический случай, если он никогда не вспомнил, что могло быть легко.
Ник Кириакидес
12
Это гипотетически. Я уверен, что премьер-министр заставит нас преследовать это столько, сколько мы можем, если он никогда не вспомнит. Я знаю, что буду.
Ник Кириакидес
59
xkcd.com/583 ;) [язык NSFW]
Балдрикк
100
«Предположим, ваша команда пишет программную систему, которая работает нормально». Перестаньте дразнить меня невозможными фантазиями!
Пол Д. Уэйт

Ответы:

134

Очевидно, что ни один руководитель проекта не потратит бесконечно много времени на решение этой проблемы. Они хотят предотвратить повторение той же ситуации.

Для достижения этой цели, даже если не удается найти основную причину такого сбоя, часто можно принять некоторые меры для

  • Обнаружьте такие сбои раньше, если они повторятся
  • Уменьшите вероятность повторения того же сбоя
  • Сделать систему более устойчивой к конкретным видам несоответствий

Например, более подробное ведение журнала, более детальная обработка ошибок или немедленная сигнализация ошибок могут помочь предотвратить повторное появление той же ошибки или найти основную причину. Если ваша система позволяет добавлять триггеры базы данных, возможно, можно добавить триггер, который запрещает вводить несоответствия в первую очередь.

Подумайте о том, какие действия можно предпринять в вашей ситуации, и предложите это команде; Я уверен, что ваш менеджер проекта будет доволен.

Однажды один из инженеров по ошибке запускает некоторые SQL-запросы, которые изменяют некоторые данные БД, а затем забывает об этом.

Как уже упоминалось другими, это также хорошая идея, чтобы запретить такую ​​процедуру (если вы влияете на то, как работает система). Никому не должно быть разрешено выполнять недокументированные специальные запросы, которые изменяют содержимое базы данных. Если такой запрос необходим, убедитесь, что существует политика для сохранения запроса вместе с датой его выполнения, именем человека, который его выполнил, и причиной его использования в задокументированном месте.

Док Браун
источник
8
@NicholasKyriakides Вероятно, оба. Все это меры здравого смысла для упрощения «отложенной» отладки. Они, вероятно, были написаны в бесчисленных процедурах.
Ник Хартли
29
Время от времени случается, что у вас возникает какая-то серьезная проблема в производственной системе, и вы не можете определить причину, несмотря на значительные усилия. В конечном счете, вы приписываете это космическим лучам и пытаетесь улучшить отчетность (поэтому, если это случится снова, у вас будет больше шансов найти причину) и смягчение последствий (так, если это произойдет снова, ущерб будет минимальным), и посмотрите, будет ли оно повторяется.
Дэвид Шварц
2
@Nicholas Kyriakides: личный опыт за несколько десятилетий.
Док Браун
4
Следует также отметить, что вполне возможно, что, даже если была ошибка, ее больше не будет. Лучшее, что вы можете иногда сделать, это исправить данные и улучшить тестирование / процедуры, чтобы избежать повторения той же проблемы.
Кучкем
2
Обнаружение периодически возникающих проблем - это всего лишь регистрация и поиск точки дросселирования, которая может обнаружить их по мере их возникновения, а затем идти назад, чтобы точно определить источник. Иногда это требует неприятных вещей, таких как триггеры или развертывание кода с шумным ведением журнала ошибок, просто чтобы понять, когда и где ошибка.
AaronLS
51

Это не ошибка

По крайней мере, не в вашем коде. Это ошибка в вашем процессе . Ваш менеджер проекта должен быть гораздо более обеспокоен вашим процессом, чем вашим кодом.

Как вы справляетесь с этим?

Проще говоря, не позволяя инженерам изменять производственные или общие базы данных для разработки .


Предполагая, что это общая база данных разработки:

В идеале, если это вообще возможно, избегать общей базы данных . Вместо этого имейте базы данных для разработчика, которые являются недолговечными. Это должно быть автоматизировано с помощью сценариев, в противном случае стоимость тестирования становится слишком большой, и есть стимул не тестировать вещи. Вы можете иметь эти базы данных либо на рабочей станции разработчика, либо на центральном сервере.

Если по какой-то причине вам абсолютно НЕОБХОДИМО иметь общую базу данных, вам следует использовать фиксаторы - по сути, то, что устанавливает базу данных в известное исправное состояние каждый раз, когда вам нужно ее использовать. Это позволяет избежать укусов разработчиков от изменений других людей.

Если вам нужно применить постоянные изменения к базе данных, вы должны зафиксировать их в вашем контроле исходного кода . Настройте свою базу данных таким образом, чтобы разработчики не имели разрешения на запись в нее напрямую, а также имели программу, которая извлекает изменения из системы контроля версий и применяет их.

Наконец, из вашего описания того, как вы отлаживаете вещи, похоже, что вы не используете CI . Используйте CI . Это немного затрудняет настройку, но в долгосрочной перспективе это сэкономит ОЧЕНЬ много времени, не говоря уже о том, чтобы помешать вам беспокоиться о невоспроизводимых ошибках базы данных. Вам останется только беспокоиться о heisenbugs сейчас!


Предполагая, что это производственная база данных:

Если ваши разработчики меняют производственные базы данных, многие вещи идут ужасно неправильно, даже если изменения абсолютно правильные.

Разработчики никогда не должны получать доступ к производственным базам данных . Там нет абсолютно никаких причин, и так много вещей, которые могут пойти очень- очень неправильно.

Если вам нужно что-то исправить в производственной базе данных, сначала создайте резервную копию, восстановите ее в другом (разрабатываемом) экземпляре, а затем поэкспериментируйте с этой базой данных разработки. Как только вы решите, что у вас есть готовое исправление (с контролем исходного кода!), Вы снова делаете восстановление, применяете исправление и видите результат. Затем, после резервного копирования данных (и, в идеале, предотвращения одновременных обновлений), вы исправляете производственный экземпляр, в идеале с помощью программного патча.

Если вам нужно что-то проверить в производственной базе данных ... нет, нет. Какие бы тесты вам ни понадобилось, вы должны делать их в экземпляре разработки. Если вам нужны данные для проведения тестов, вы получите эти данные там.

goncalopp
источник
12
Итак, ваше рекомендуемое решение - путешествие во времени?
Benubird
7
Хотя это достойное решение для данного примера, вопрос имеет гораздо более общий контекст работы с ошибками, которые невозможно воспроизвести, и менеджерами, которые хотят, чтобы они их исправляли. Это может относиться не только к проблемам с базой данных и управлению разрешениями. Я чувствую, что этот ответ на самом деле не отвечает на поставленный вопрос, а только на данном примере.
Кайл Уордл
@KyleWardle Согласен. Я думаю, что ответ Дока Брауна достаточно хорошо охватывает общий случай (подробное ведение журнала и обработка ошибок, условия охраны). Я в основном добавил свой, потому что я видел, что никто не упомянул сбои процессов, которые привели к проблеме в первую очередь
goncalopp
2
@Benubird Я думаю, что ответ сводится к тому, «то, как вы справляетесь с этим, предотвращает его повторение». Я не думаю, что вы можете «решить» поврежденную производственную базу данных с точки зрения разработки программного обеспечения.
goncalopp
1
Вы не собираетесь менять код для помещения данных в базу данных разработчиков. Везде, где я работал, включая крупные корпорации, разработчики могут свободно вставлять тестовые данные и использовать те же учетные данные, которые использует приложение.
Дэвид Конрад
13

Производственная база данных должна иметь полное управление доступом и управление доступом на основе ролей. Таким образом, у вас должны быть веские доказательства того, что ВОЗ сделала, ЧТО, КОГДА-ЛИБО, для базы данных, таким образом, переключая внимание с кода на плохую безопасность работы.

Дон гилман
источник
2
Похоже, что они могут не знать точно, когда произошло повреждение данных, что может затруднить выяснение того, какие журналы им нужно исследовать.
Натанаэль
3
К сожалению, при обнаружении одного из них мы обнаружили, что он также уничтожает логи. (Да, это. Ошибка была реальной.)
Джошуа
Параллельное ведение журнала с запланированными заданиями, проверяющими целостность данных, даже если это происходит только в одночасье, означает, что проблемы могут быть помечены заранее и решены. Если вы хотите быть очень осторожным, требуйте экспертной оценки изменений.
Кит
Везде, где я работал, разработчики подключаются к базе данных с теми же учетными данными, которые использует приложение, поэтому регистрация доступа будет отображаться только тогда, когда этот идентификатор внес изменение, а не то, что это сделал человек, а не программа. Я полагаю, вы могли бы сравнить временную метку с журналами приложений, чтобы увидеть, делает ли приложение что-либо, что будет записывать в базу данных в то время.
Дэвид Конрад
@DavidConrad: Почему разработчики имеют доступ к учетным данным, которые приложение использует в работе? Вам следует использовать какое-то секретное управление, чтобы эти учетные данные не могли быть прочитаны, за исключением вашей учетной записи службы приложений, с рабочих серверов приложений.
Даниэль Приден
6

В этом случае вы, в конечном счете, выяснили причину, но взяли гипотетическое, что вы не ...

Сначала проанализируйте, что изменилось. Если система раньше работала нормально, внимательный взгляд на все, что было сделано в последнее время, может выявить изменения, вызвавшие ошибку. Систематически проверяйте свой контроль версий, CI / системы развертывания и контроль конфигурации, чтобы увидеть, изменилось ли что-нибудь. Запустите git bisect или эквивалентный механизм для выполнения двоичного поиска. Проверьте логи. Охотьтесь за бревнами, о которых не знали. Поговорите со всеми, кто имеет доступ к системе, чтобы узнать, сделали ли они что-нибудь в последнее время. Для вашей проблемы, если вы достаточно основательны в этом процессе, надо надеяться, что вы обнаружите забытые SQL-запросы.

Во-вторых, приборостроение. Если вы не можете напрямую найти причину ошибки, добавьте инструментарий вокруг нее, чтобы собрать данные о проблеме. Спросите себя «могу ли я воспроизвести эту ошибку по команде, что бы я хотел посмотреть в отладчике», а затем запишите это. Повторяйте по мере необходимости, пока у вас не будет лучшего понимания проблемы. Как рекомендует Док Браун, добавьте ведение журнала для состояний, имеющих отношение к ошибке. Добавьте утверждения, которые обнаруживают поврежденные данные. Например, если ваша ошибка - сбой приложения, добавьте механизм ведения журнала сбоев. Если у вас уже есть один, отлично, добавьте аннотации в журналы сбоев, чтобы записать состояние, потенциально относящееся к сбою. Подумайте, могут ли быть проблемы с параллелизмом, и протестируйте их для обеспечения безопасности потоков .

В-третьих, устойчивость. Ошибки неизбежны, поэтому спросите себя, как вы можете улучшить свои системы, чтобы сделать их более устойчивыми, чтобы облегчить восстановление после ошибки. Могут ли ваши резервные копии быть улучшены (или существуют)? Лучший мониторинг, аварийное переключение и оповещение? Больше избыточности? Лучшая обработка ошибок? Отделить зависимые услуги друг от друга? Можете ли вы улучшить свои процессы, связанные с доступом к базе данных и ручными запросами? В лучшем случае, эти вещи сделают последствия вашей ошибки менее серьезными, а в худшем случае они, вероятно, будут хорошими действиями в любом случае.

Зак Липтон
источник
5
  1. Объясните своему руководителю проекта, что, по вашему мнению, наиболее вероятной причиной является ручной доступ к базе данных.
  2. Если они по-прежнему хотят, чтобы вы искали код, вызвавший это, отправляйтесь и посмотрите на код еще раз.
  3. Вернитесь через пару часов (или в другое подходящее время) и скажите, что вы не можете найти какой-либо код, который вызвал бы это, поэтому вы все еще считаете, что наиболее вероятной причиной является ручной доступ к базе данных.
  4. Если они все еще хотят, чтобы вы искали код, спросите, сколько времени они хотели бы, чтобы вы потратили на это. Слегка напомните им, что вы не будете работать над функцией X, ошибкой Y или улучшением Z, пока вы делаете это.
  5. Потратьте столько времени, сколько они просят. Если вы все еще думаете, что наиболее вероятной причиной является ручной доступ к базе данных, сообщите им об этом.
  6. Если они все еще хотят, чтобы вы искали код, обострите проблему, поскольку это явно стало непродуктивным использованием времени вашей команды.

Вы также можете подумать о том, следует ли вам добавить дополнительные процессы, чтобы уменьшить вероятность ручного доступа к базе данных, вызывающего подобные проблемы в будущем.

Филип Кендалл
источник
1
Я понятия не имел, что один из инженеров сделал обновление вручную + инженеры почти никогда не запускают запросы непосредственно в базе данных. Этот просто сделал, как разовую вещь и забыл об этом. Мы потратили целый день на подготовку к тому, чтобы выяснить, в чем дело. Мой вопрос заключается в том, что произойдет, если вы не можете найти причину и не можете предположить, какой может быть потенциальная причина.
Ник Кириакидес
5
«Мой вопрос заключается в том, что происходит, если вы не можете найти причину и не можете предположить, что это может быть за потенциальная причина». Именно по этой причине был изобретен флаг «не исправить - не продублировать».
Эзотерик
4

Я работал в команде разработчиков продукта баз данных для мэйнфреймов, когда клиент сообщил, что у него поврежденная база данных. Повреждение в том смысле, что внутреннее состояние битов на диске означало, что база данных не читалась через программное обеспечение базы данных. В мире мейнфреймов клиенты платят вам миллионы долларов, и вы должны относиться к этому серьезно. Вот что мы сделали:

Шаг 0: помогите клиенту снова начать работу, восстановив базу данных.

Шаг 1: изучив файл на диске на шестнадцатеричном уровне, мы определили, что повреждение было систематическим: было много случаев одного и того же повреждения. Так что это определенно было вызвано на уровне программного обеспечения базы данных. Действительно, это было достаточно систематично, и мы чувствовали, что можем исключить проблемы с многопоточностью.

После устранения многих других теорий мы нашли утилиту, которая могла бы использоваться для физической реорганизации базы данных. Казалось, это единственный код, который имел доступ к данным на нужном уровне. Затем мы обнаружили способ запуска этой утилиты с тщательно подобранными параметрами, которые воспроизводили проблему. Клиент не смог подтвердить или опровергнуть, что это то, что он сделал, но так как это было единственное объяснение, которое мы могли придумать, мы решили, что это была вероятная причина, и у них не было иного выбора, кроме как принять наш диагноз ,

Шаг 2: Затем мы сделали два изменения в программном обеспечении: (а) усложнили случайный запуск этого эффекта через пользовательский интерфейс «да, я знаю, что я делаю», и (б) добавили новый файл журнала, чтобы, если это когда-нибудь случится снова, у нас будет запись действий пользователя.

Таким образом, в основном (а) устраните ущерб и восстановите работоспособность, (б) найдите основную причину, (в) сделайте все, что нужно, чтобы предотвратить его повторение или чтобы облегчить диагностику, если это произойдет снова.

Майкл Кей
источник
3

Исходя из моего опыта, то, что хочет ваш босс, является некоторой гарантией того, что это не повторится. Если дело в том, что ни один код не был причиной, потому что это обеспечивается единичным тестированием, поэтому при условии, что у вас уже есть покрытие для тестирования вашей базы кода, решение должно добавить «тестирование» в вашу базу данных. Я процитирую Дона Гилмана, потому что он прибил там:

Производственная база данных должна иметь полное управление доступом и управление доступом на основе ролей. Таким образом, у вас должны быть веские доказательства того, что ВОЗ сделала, ЧТО, КОГДА-ЛИБО, для базы данных, таким образом, переключая внимание с кода на плохую безопасность работы.

Но также вы должны иметь стандартную рабочую процедуру для изменения данных в производстве. Например, ни один администратор базы данных не должен изменять данные, ни один разработчик не должен выполнять это изменение самостоятельно, и они должны, как определено в СОП, формально требовать друг от друга изменения по почте или в билете.

Где-то должна быть такая цитата, если нет, можете привести меня к ней:

У поваров нет веских причин не отвечать за чистку туалетов.

CesarScur
источник
1

Есть несколько вещей, которые должны быть сделаны с невоспроизводимыми ошибками.

  1. Создайте билет для этого

Создайте заявку и запишите все, что вы можете придумать, в заявке. Также проверьте, был ли ранее зарегистрирован этот «баг», и свяжите заявки вместе. В конце концов вы можете получить достаточно билетов, чтобы установить шаблон для воспроизведения ошибки. Это включает обходные пути, используемые, чтобы попытаться избежать этого. Даже если это единственный случай, если в первый раз, в конечном итоге будет второй раз. Когда вы найдете причину, закройте тикет с объяснением причины, чтобы у вас было четкое представление о том, что произошло, если это произойдет снова (исправление потеряно при неправильном слиянии)

  1. Сделать анализ твердения

Посмотрите на систему, что не удалось, и как это не удалось. Попробуйте найти области кода, которые можно обновить, чтобы уменьшить вероятность сбоя. Некоторые примеры...

  • Заменить код однорангового с выделенным вызовом (например , execute(<query>)сexecuteMyStoredProcedure(<params>)
  • Запустите сценарии ночной проверки для проверки целостности данных (чтобы в следующий раз это можно было обнаружить в течение 24 часов)
  • Добавить / улучшить ведение журнала и архивирование (резервное копирование).
  • Измените неправильные ограничения безопасности (например, люди / программы, которые только читают данные, не имеют разрешения на запись; не позволяя разработчикам, которые не несут ответственности за производство, иметь возможность войти на рабочие серверы)
  • Добавить данные проверки / санитарии, где отсутствует

Это может не исправить ошибку, но даже если это не так, система теперь более стабильна / безопасна, поэтому она окупается.

  1. Добавить системные оповещения

Вроде часть 2, но что-то случилось, и вам нужно знать, когда это произойдет снова. Вы должны создать несколько сценариев / программ проверки работоспособности для мониторинга системы, чтобы администраторы могли быть предупреждены в течение 24 часов после устранения ошибки (чем меньше задержка, тем лучше, в пределах разумного). Это сделает уборку намного легче. (Обратите внимание, что в дополнение к журналам баз данных ОС также должна регистрировать, кто входит в нее, и любые нечитаемые действия, которые они выполняют. По крайней мере, должны быть сетевые журналы трафика на эту машину)

Tezra
источник
0

Ваша проблема была вызвана не ошибкой в ​​вашем программном обеспечении, а тем, что кто-то возился с базой данных. Если вы называете ошибки «ошибкой», то ваша ошибка легко воспроизводима: когда кто-то делает глупости с базой данных, все пойдет не так. И есть способы избежать этой «ошибки», не позволяя изменять базу данных вручную или используя непроверенное программное обеспечение, и строго контролируя, кто может изменять базу данных.

Если вы называете ошибки в своей базе данных «ошибкой», то у вас нет невоспроизводимой ошибки, у вас ее вообще нет. У вас может быть отчет об ошибке, но у вас также есть доказательства того, что проблема не была вызвана ошибкой. Таким образом, вы можете закрыть отчет об ошибке не как «невоспроизводимый», а как «поврежденная база данных». Нередко появляются сообщения об ошибках, где расследование показывает, что ошибки нет, но пользователь использовал программное обеспечение неправильно, ожидания пользователя были неверны и т. Д.

В этом случае вы все еще знаете, что была проблема, которую вы не хотите повторять, поэтому вы предпринимаете те же действия, что и в первом случае.

gnasher729
источник