web-dev-qa-db-ja.com

再現できないバグへの対処

あなたのチームが(驚くほど)正常に動作しているソフトウェアシステムを作成するとします。

ある日、エンジニアの1人が誤っていくつかのSQLクエリを実行し、DBデータの一部を変更した後、それを忘れてしまいました。

しばらくして、破損した/誤ったデータを発見し、誰もがコードのどの部分がこれを引き起こしたのか、なぜ失敗したのかについて頭を掻きます。一方、プロジェクトマネージャーは、それを引き起こしたコードの一部を見つけることを求めています。

これにどう対処しますか?

72
Nik Kyriakides

このような問題に無限の時間を費やすプロジェクトマネージャーがいないことは明らかです。彼らは同じ状況が再び起こるのを防ぎたいと思っています。

この目標を達成するために、そのような失敗の根本的な原因を見つけることができなくても、多くの場合、いくつかの対策を講じることが可能です。

  • それらが再発する場合に備えて、このような障害を早期に検出する
  • 同じ失敗が再び発生する可能性を低くする
  • 特定の種類の不整合に対してシステムをより堅牢にする

たとえば、より詳細なログ記録、よりきめ細かいエラー処理、または即時のエラーシグナリングは、同じエラーが再び発生するのを防ぐ、または根本的な原因を見つけるのに役立ちます。システムでデータベーストリガーの追加が許可されている場合は、最初に導入される不整合を禁止するトリガーを追加することができます。

あなたの状況で適切な種類の行動が何であるかを考え、これをチームに提案します。きっとあなたのプロジェクトマネージャーは喜ぶでしょう。

ある日、エンジニアの1人が誤っていくつかのSQLクエリを実行し、DBデータの一部を変更した後、それを忘れてしまいました。

他の人が述べたように、このような手順を禁止することもお勧めします(システムの操作方法に影響がある場合)。データベースのコンテンツを変更する、文書化されていないアドホッククエリの実行を誰にも許可するべきではありません。そのようなクエリが必要な場合は、クエリをその実行日、実行者の名前、および使用された理由とともに文書化された場所に格納するポリシーがあることを確認してください。

134
Doc Brown

これはバグではありません

少なくともあなたのコードでは。 プロセスのバグです。プロジェクトマネージャーは、コードよりもプロセスをはるかに心配する必要があります。

これにどう対処しますか?

簡単に言うと、エンジニアに本番データベースまたは共有開発データベースを変更させないことです


これが共有開発データベースであると仮定します。

理想的には、可能な限り、最初に共有データベースを使用しないようにします。代わりに、有効期間が短い開発者ごとのデータベースを用意してください。これはスクリプトで自動化する必要があります。そうしないと、テストのコストが高すぎて、テストしないインセンティブがあります。これらのデータベースは、開発者のワークステーションまたは中央サーバーに置くことができます。

何らかの理由で、共有データベースが絶対に必要な場合は、基本的に fixtures -を使用する必要があります。これは、使用するたびにデータベースを既知の良好な状態に設定するものです。これにより、開発者が他の人の変更に噛まれるのを防ぎます。

データベースに永続的な変更を適用する必要がある場合は、それらをソース管理にコミットする必要があります。開発者がデータベースに直接書き込む権限を持たないようにデータベースを設定し、ソース管理から変更をプルして適用するプログラムを用意します。

最後に、デバッグ方法の説明から、 [〜#〜] ci [〜#〜] を使用していないようです。 CIを使用します。設定は少し面倒ですが、長期的にはSO大幅に時間を節約できます。言うまでもなく、データベースの再現性のないバグについて心配する必要はありません。心配するだけで済みます。 heisenbugs について!


これが本番データベースであると仮定します。

開発者が本番データベースを変更している場合、たとえ変更が完全に正しいとしても、多くのことがひどく間違っています。

開発者は本番データベースにアクセスしないでください。絶対に理由はなく、非常に非常に間違っている可能性のある多くのこと

本番データベースの何かをfixする必要がある場合は、最初にバックアップし、そのバックアップをdifferent(開発)インスタンスに復元します。そしてそしてその開発データベースをいじります。 (ソース管理で!)修正の準備ができたと思ったら、復元をやり直して修正を適用し、結果を確認します。次に、物事を再度バックアップした後(理想的には同時更新を防止した後)、理想的にはソフトウェアパッチを使用して本番インスタンスを修正します。

運用データベースで何かをtestする必要がある場合...いいえ、必要ありません。必要なテストが何であれ、開発インスタンスで行う必要があります。テストを実行するためにデータが必要な場合は、そこにそのデータを取得します。

50
goncalopp

運用データベースには、完全なアクセスログとロールベースのアクセス制御が必要です。したがって、WHOがデータベースに対して何をしたかについての確固たる証拠が必要であり、コードから注意が不十分な運用上のセキュリティに移されます。

13
Don Gilman

この場合、最終的に原因を突き止めましたが、あなたがしなかったという仮説を立てます...

まず、何が変わったかを分析します。システムが以前正常に動作していた場合、最近行われたすべてを注意深く見ると、バグの原因となった変更が明らかになる可能性があります。バージョン管理、CI /デプロイメントシステム、構成管理を体系的に確認して、変更点がないか確認します。 git bisectまたは同等のメカニズムを実行して、バイナリ検索を実行します。ログを確認してください。知らないログを探しましょう。システムにアクセスできるすべての人と話し、最近何かをしたかどうかを確認します。あなたの問題については、このプロセスを十分に理解していれば、忘れられていたSQLクエリが明らかになるはずです。

第二に、計測。バグの原因を直接見つけることができない場合は、その周りに計測を追加して、問題に関するデータを収集します。 「このバグをコマンドで再現できたら、デバッガで何を確認したいですか」と自問し、それを記録します。問題をよりよく理解するまで、必要に応じて繰り返します。 Doc Brownが示唆するように、バグに関連する状態のログを追加します。破損したデータを検出するアサーションを追加します。たとえば、バグがアプリケーションのクラッシュである場合は、クラッシュロギングメカニズムを追加します。素晴らしいものがある場合は、クラッシュログに注釈を追加して、クラッシュに関連する可能性のある状態を記録します。同時実行の問題が関係しているかどうかを検討し、 スレッド安全性をテストする を検討します。

第三に、弾力性。バグは避けられないので、バグからの回復が簡単になるようにシステムをどのように回復力を高めるように改善できるかを自問してください。バックアップを改善できますか(または存在しますか)?監視、フェイルオーバー、アラートの改善?冗長性を高めますか?エラー処理の改善?依存しているサービスを互いに分離しますか?データベースアクセスと手動クエリに関するプロセスを改善できますか?せいぜい、これらのことはあなたのバグの結果をそれほど深刻にしません、そして最悪の場合、それらはおそらくとにかくやるべき良いことです。

6
Zach Lipton
  1. ほとんどの場合の原因は手動によるデータベースアクセスであるとプロジェクトマネージャーに説明します。
  2. 彼らがあなたにこれを引き起こしたコードを探してほしいと望むなら、行ってコードをもう一度見てもらいます。
  3. 数時間後(または他の適切な時間)に戻って、これを引き起こしたコードが見つからない場合は、手動によるデータベースアクセスが原因であると考えられます。
  4. 彼らがまだにコードを探して欲しい場合は、これに費やす時間を尋ねてください。これを行っている間は、機能X、バグY、または拡張Zで作業しないことを微妙に思い出させてください。
  5. 彼らが望むだけ多くの時間を費やしてください。それでも最も可能性の高い原因が手動のデータベースアクセスであると思われる場合は、これを伝えてください。
  6. 彼らがまだにコードを探して欲しい場合は、問題をエスカレーションしてください。これは明らかにチームの時間の非生産的な使用になります。

また、将来このような問題を引き起こす手動のデータベースアクセスの可能性を減らすために、追加のプロセスを追加する必要があるかどうかを検討することもできます。

5
Philip Kendall

データベースが破損しているとお客様から報告されたとき、私はメインフレームデータベース製品の開発チームで作業していました。ディスク上のビットの内部状態がデータベースをデータベースソフトウェア経由で読み取ることができないことを意味するという意味での破損。メインフレームの世界では、顧客は何百万ドルも払っていますが、これを真剣に受け止める必要があります。これが私たちがしたことです:

ステップ0:データベースを修復することにより、お客様が再び稼働できるようにします。

手順1:ディスク上のファイルを16進レベルで調べると、破損が系統的であることがわかりました。同じ破損のインスタンスが多数ありました。したがって、それは間違いなくデータベースソフトウェアのレベルで発生しました。実際、マルチスレッドの問題を除外できると感じたのは十分に体系的でした。

データベースの物理的な再編成に使用できるユーティリティに基づいて他の多くの理論を排除した後。適切なレベルでデータにアクセスできる唯一のコードのようです。その後、慎重に選択されたオプションを使用してこのユーティリティを実行する方法を発見し、問題を再現しました。お客様は、これが彼らのしたことであることを確認または否定することはできませんでしたが、考えられる唯一の説明であったため、考えられる原因であると判断し、診断を受け入れるしかありませんでした。 。

ステップ2:次に、ソフトウェアに2つの変更を加えました。(a)「私がやっていることを知っている」ユーザーインターフェイスを介して、この影響を誤って引き起こしにくくし、(b)新しいログファイルを導入して、それが二度と起こらなかった場合、ユーザーのアクションの記録ができます。

つまり、基本的には、(a)損傷を修復してライブランニングを復元する、(b)根本原因を見つける、(c)再発を防止するため、または再発した場合に簡単に診断できるようにするために必要なことをすべて実行します。

4
Michael Kay

私の経験から、あなたの上司が望んでいるのは、これが再発しないというある程度の保証です。コードが原因でなかった場合は、それがユニティテストによって保証されているため、コードベースのテストカバレッジがすでにあると想定すると、ソリューションはデータベースに「テスト」を追加する必要があります。ドンギルマンを引用します。

運用データベースには、完全なアクセスログとロールベースのアクセス制御が必要です。したがって、WHOがデータベースに対して何をしたかについての確固たる証拠が必要であり、コードから注意が不十分な運用上のセキュリティに移されます。

ただし、本番環境でのデータ変更に関する標準操作手順も必要です。たとえば、DBAがデータを変更したり、開発者が自分で変更を実行したりする必要はなく、SOPで定義されているように、メールまたはチケットによる変更を互いに正式に要求する必要があります。

どこかにこのような引用があるはずですが、もしそうでなければ引用してください。

シェフがトイレの掃除を担当していないのには、完全に正当な理由があります。

3
CesarScur

再現性のないバグで実行する必要があるいくつかのことがあります。

  1. チケットを作成

チケットを作成し、考えられるすべてのものをチケットに記録します。また、この「バグ」が以前にログに記録されているかどうかを確認し、チケットをリンクします。最終的には、バグを再現する方法のパターンを確立するのに十分なチケットを取得できます。これには、回避するために使用される回避策が含まれます。これが唯一のインスタンスであっても、初めての場合、最終的には2回目になります。原因が見つかったら、原因が何であるかを説明したチケットを閉じて、問題が再発した場合に何が起こったのかをよく理解できるようにします(悪いマージで修正が失われる)。

  1. 強化分析を行う

システム、何が失敗したか、どのように失敗したかを確認します。失敗の可能性を低くするために更新できるコードの領域を見つけてみてください。いくつかの例...

  • アドホックコードを専用の呼び出しに置き換えます(execute(<query>)executeMyStoredProcedure(<params>)で置き換えるなど)
  • 毎晩検証スクリプトを実行して、データの整合性を検証します(これにより、次回24時間以内にこれを検出できるようになります)
  • ロギングとアーカイブ(バックアップ)を追加/改善します。
  • 不適切なセキュリティ制限を変更します(たとえば、データを読み取るだけのユーザー/プログラムには書き込み権限がありません。実稼働に責任のない開発者が実稼働サーバーにログインできないようにします)。
  • 欠落している場所にデータ検証/衛生設備を追加する

これでバグは修正されない可能性がありますが、修正されなくても、システムの安定性と安全性が向上し、成果が上がります。

  1. システムアラートを追加する

2のちょっとした部分ですが、何かが起こりました、そしてそれがいつ再び起こるかを知る必要があります。システムを監視するためにいくつかのヘルスチェックスクリプト/プログラムを作成して、バグの再浮上から24時間以内に管理者にアラートを送信できるようにする必要があります(遅延が少ないほど、適切です)。これにより、クリーンアップがはるかに簡単になります。 (データベースのログに加えて、OSは、ログインしたユーザーと、それらが実行する読み取り以外のアクションもログに記録する必要があります。少なくとも、そのマシンへのトラフィックのネットワークログが存在する必要があります)

1
Tezra

問題の原因はソフトウェアの障害ではなく、データベースをいじる人です。問題を「バグ」と呼ぶ場合、バグは簡単に再現できます。誰かがデータベースに対して愚かなことをすると、常に問題が発生します。また、この「バグ」を回避するには、データベースを手動で変更できないようにするか、テストされていないソフトウェアを使用して、データベースを変更できるユーザーを厳密に制御する方法があります。

データベースの障害を「バグ」と呼ぶだけであれば、再現できないバグはなく、バグはまったくありません。バグレポートがあるかもしれませんが、問題の原因がバグではないという証拠もあります。したがって、「再現不能」ではなく、「破損したデータベース」のようなバグレポートを閉じることができます。調査でバグがないことを示すバグレポートがあることは珍しくありませんが、ユーザーがソフトウェアを間違って使用した、ユーザーの期待が間違っていた、などです。

その場合でも、繰り返したくない問題があることがわかっているので、最初のケースと同じアクションを実行します。

0
gnasher729