재현 할 수없는 버그 다루기


73

팀이 훌륭하게 실행되는 소프트웨어 시스템을 작성한다고 가정하십시오.

어느 날 엔지니어 중 한 명이 일부 DB 데이터를 변경하는 일부 SQL 쿼리를 실수로 실행 한 다음 잊어 버렸습니다.

시간이 지나면 손상된 / 오류가있는 데이터를 발견하고 모든 사람이 코드의 어느 부분에서이 문제를 일으켰는지에 대해 머리를 긁습니다. 한편 프로젝트 관리자는 코드의 일부를 찾은다고 주장합니다.

이것을 어떻게 처리합니까?


32
엔지니어가 잊어 버린 경우 어떻게 된 일인지 어떻게 알 수 있습니까? 버그가 아닌 스크립트를 실행하는 사람이 어떻게 손상 되었습니까?
DaveG

18
그는 하루나 이틀 후에 주현절이있었습니다. 이것은 그가 쉽게 그랬을지도 모른다는 것을 결코 기억하지 못하는 경우에 대비 한 가설이다.
Nik Kyriakides

12
이것은 가설입니다. 나는 PM이 우리가 그가 결코 기억하지 못한다면 우리가 할 수있는 한 많은 것을 쫓아 갈 것이라고 확신한다. 내가 할 줄 알아
Nik Kyriakides

59
xkcd.com/583 ) [NSFW 언어]
Baldrickk

100
"귀하의 팀이 제대로 운영되는 소프트웨어 시스템을 작성하도록하십시오."불가능한 환상으로 나를 괴롭히지 마십시오!
Paul D. Waite

답변:


134

프로젝트 관리자는 그러한 문제에 무한한 시간을 투자하지 않을 것입니다. 그들은 같은 상황이 다시 발생하는 것을 막기를 원합니다.

이러한 목표를 달성하기 위해 그러한 실패의 근본 원인을 찾을 수없는 경우에도 다음과 같은 조치를 취할 수 있습니다.

  • 그들이 다시 발생하는 경우 조기에 그러한 실패를 감지
  • 동일한 실패가 다시 발생할 가능성을 줄입니다.
  • 특정 종류의 불일치에 대해 시스템을 더욱 강력하게 만듭니다.

예를 들어,보다 자세한 로깅,보다 세밀한 오류 처리 또는 즉각적인 오류 신호는 동일한 오류가 다시 발생하는 것을 방지하거나 근본 원인을 찾는 데 도움이 될 수 있습니다. 시스템에서 데이터베이스 트리거 추가를 허용하는 경우 처음에 불일치가 발생하는 것을 금지하는 트리거를 추가 할 수 있습니다.

상황에 맞는 적절한 행동이 무엇인지 생각하고이를 팀에 제안하십시오. 프로젝트 관리자가 기뻐할 것입니다.

어느 날 엔지니어 중 한 명이 일부 DB 데이터를 변경하는 일부 SQL 쿼리를 실수로 실행 한 다음 잊어 버렸습니다.

다른 사람들이 언급했듯이 그러한 절차를 금지하는 것이 좋습니다 (시스템 작동 방식에 영향을 미치는 경우). 데이터베이스 내용을 변경하는 문서화되지 않은 임시 쿼리를 실행해서는 안됩니다. 이러한 쿼리가 필요한 경우 쿼리를 실행 날짜, 실행 한 사람의 이름 및 사용 이유와 함께 문서화 된 장소에 쿼리를 저장하는 정책이 있는지 확인하십시오.


8
@NicholasKyriakides 아마 둘 다. 이 모든 것은 "지연된"디버깅을 더 단순하게 만드는 상식적인 조치입니다. 그들은 아마도 무수한 절차로 쓰여졌을 것입니다.
Nic Hartley

29
프로덕션 시스템에서 심각한 문제가 발생하여 상당한 노력에도 불구하고 원인을 파악하지 못하는 경우가 종종 있습니다. 궁극적으로이를 우주 광선으로보고보고를 향상 시키려고 시도합니다 (따라서 다시 발생하면 원인을 찾을 가능성이 더 높음). 반복합니다.
David Schwartz

2
@Nicholas Kyriakides : 수십 년에 걸친 개인적인 경험.
Doc Brown

4
또한 버그가 있어도 더 이상 존재하지 않을 가능성이 매우 높습니다. 때때로 수행 할 수있는 최선의 방법은 데이터를 수정하고 테스트 / 프로 시저를 개선하여 동일한 문제가 다시 발생하지 않도록하는 것입니다.
kutschkem

2
간헐적 인 문제를 찾는 것은 문제가 발생했을 때이를 탐지 할 수있는 초크 포인트를 로깅하고 찾은 다음 뒤로 이동하여 소스를 찾아내는 것입니다. 때로는 언제 어디서 오류를 처리하기 위해 트리거 또는 시끄러운 오류 로그가있는 코드 배포와 같은 불쾌한 것들이 필요합니다.
AaronLS

51

이것은 버그가 아닙니다

적어도 코드에는 없습니다. 그것은 프로세스 의 버그입니다 . 프로젝트 관리자는 코드보다 프로세스에 대해 훨씬 더 걱정해야합니다.

이것을 어떻게 처리합니까?

간단히 말해 엔지니어가 생산 또는 공유 개발 데이터베이스를 변경하지 못하게함으로써 .


이것이 공유 개발 데이터베이스라고 가정합니다.

이상적으로는 가능하다면 공유 데이터베이스를 먼저 사용하지 마십시오 . 대신 개발자마다 데이터베이스 수명이 짧습니다. 스크립트로 자동화해야합니다. 그렇지 않으면 테스트 비용이 너무 커져서 테스트하지 않는 동기가 있습니다. 이 데이터베이스를 개발자 워크 스테이션 또는 중앙 서버에 둘 수 있습니다.

어떤 이유로 든 공유 데이터베이스를 반드시 가져야하는 경우, 고정구 를 사용해야합니다. 기본적으로 데이터베이스를 사용할 때마다 알려진 상태로 설정하는 것입니다. 이것은 개발자들이 다른 사람들의 변화에 ​​물린 것을 피합니다.

데이터베이스에 영구적 인 변경 사항을 적용해야하는 경우 소스 제어에이를 변경해야합니다 . 개발자가 데이터베이스에 직접 쓸 수있는 권한을 갖지 않도록 데이터베이스를 설정하고 소스 제어에서 변경 사항을 가져 와서 적용하는 프로그램이 있어야합니다.

마지막으로, 디버깅 방법에 대한 설명에서 CI를 사용하지 않는 것처럼 들립니다 . CI를 사용하십시오 . 설정하기에는 약간의 어려움이 있지만 장기적으로 너무 많은 시간을 절약 할 수 있으며 재현 할 수없는 데이터베이스 버그에 대해 걱정하지 않아도됩니다. 이제 이젠 버그만 걱정하면됩니다 !


이것이 프로덕션 데이터베이스라고 가정합니다.

개발자가 프로덕션 데이터베이스를 변경하는 경우 변경 사항이 정확하더라도 많은 일이 잘못되었습니다.

개발자는 프로덕션 데이터베이스에 액세스해서는 안됩니다 . 그럴 이유가없고, 매우 잘못 될 수있는 많은 것들이 있습니다 .

프로덕션 데이터베이스에서 무언가 를 수정 해야하는 경우 먼저 백업하고 다른 (개발) 인스턴스에서 해당 백업을 복원 한 다음 해당 개발 데이터베이스 재생하십시오. 소스 제어에서 수정 사항이 준비되었다고 생각되면 복원을 다시 수행하고 수정 사항을 적용한 후 결과를보십시오. 그런 다음 다시 백업 한 후 (이상적으로 동시 업데이트 방지) 소프트웨어 패치를 통해 프로덕션 인스턴스를 수정합니다.

프로덕션 데이터베이스에서 무언가 를 테스트 해야하는 경우 ... 아닙니다. 어떤 테스트를 수행해야하는지 개발 인스턴스에서 수행해야합니다. 테스트를 수행하기 위해 데이터가 필요한 경우 해당 데이터를 얻을 수 있습니다.


12
따라서 권장되는 솔루션은 시간 여행입니까?
Benubird

7
이것은 주어진 예에 대한 적절한 해결책이지만 문제는 재현 할 수없는 버그와 버그를 다루기를 원하는 관리자를 다루는 훨씬 일반적인 상황입니다. 이는 데이터베이스 문제 및 권한 관리 그 이상에 적용될 수 있습니다. 이 답변이 실제로 의도 한 질문에 대답하는 것이 아니라 주어진 예에 불과하다고 생각합니다.
Kyle Wardle

@KyleWardle 합의. Doc Brown의 대답은 일반적인 경우 (상세한 로깅 및 오류 처리, 가드 조건)를 잘 다루고 있다고 생각합니다. 나는 아무도 처음부터 문제에지도 과정의 실패를 언급 없었다 보았 기 때문에 나는 주로 내 추가
goncalopp

2
@Benubird 나는 그 대답이 "이것을 다루는 방식이 다시는 일어나지 못하게 막는 것"으로 귀결된다고 생각합니다. 소프트웨어 엔지니어링 관점에서 손상된 프로덕션 데이터베이스를 "해결"할 수 없다고 생각합니다.
goncalopp

1
개발자 데이터베이스에 데이터를 넣는 코드를 변경하지 않을 것입니다. 대기업을 포함하여 내가 일한 모든 곳에서 개발자는 테스트 데이터를 자유롭게 삽입하고 응용 프로그램이 사용하는 것과 동일한 자격 증명을 사용할 수 있습니다.
David Conrad

13

프로덕션 데이터베이스에는 전체 액세스 로깅 및 역할 기반 액세스 제어가 있어야합니다. 따라서 WHO가 데이터베이스에 대해 무엇을했는지에 대한 확실한 증거가 있어야 코드에서주의하지 않은 운영 보안으로 관심을 이동시킬 수 있습니다.


2
데이터 손상이 발생한시기를 정확히 알지 못하는 것처럼 들리므로 조사해야 할 로그를 파악하기가 어려울 수 있습니다.
Nathanael

3
불행히도 이것들 중 하나를 추적하면서 로그를 휴지통으로 옮기는 것을 발견했습니다. (예, 그렇습니다. 버그는 실제로 발생했습니다.)
Joshua Joshua

예약 된 작업으로 몇 시간 만이라도 데이터 무결성을 검사하는 로깅은 문제를 조기에 신고하고 해결할 수 있음을 의미합니다. 정말로주의를 기울이려면 변경 사항에 대해 동료 검토가 필요합니다.
Keith

모든 곳에서 개발자가 앱에서 사용하는 것과 동일한 자격 증명을 사용하여 데이터베이스에 연결했기 때문에 액세스 로깅은 해당 ID가 변경되었을 때만 나타납니다. 타임 스탬프와 응용 프로그램 로그를 비교하여 응용 프로그램이 그 당시 DB에 쓰는 작업을 수행하고 있는지 확인할 수 있다고 가정합니다.
David Conrad

@DavidConrad : 개발자가 앱이 프로덕션 환경에서 사용하는 자격 증명에 액세스 할 수있는 이유는 무엇입니까? 프로덕션 응용 프로그램 서버에서 응용 프로그램 서비스 계정을 제외하고 이러한 자격 증명을 읽을 수 없도록 일종의 비밀 관리를 사용해야합니다.
Daniel Pryden

6

이 경우, 당신은 궁극적으로 원인을 알아 냈지만 당신이하지 않았다는 가설을 세웁니다.

먼저 변경된 내용을 분석하십시오. 이전에 시스템이 제대로 작동했다면 최근에 수행 된 모든 사항을주의 깊게 살펴보면 버그의 원인이 된 변경 사항이 드러날 수 있습니다. 버전 제어, CI / 배포 시스템 및 구성 제어를 체계적으로 검토하여 변경된 사항이 있는지 확인하십시오. 이진 검색을 수행하려면 git bisect 또는 이와 동등한 메커니즘을 실행하십시오. 로그를 확인하십시오. 당신이 알지 못했던 통나무를 찾으십시오. 시스템에 액세스 할 수있는 모든 사람과 대화하여 최근에 수행 한 작업이 있는지 확인하십시오. 문제의 경우,이 과정에서 충분히 철저하다면 잊어 버린 SQL 쿼리를 공개해야합니다.

둘째, 계측. 버그의 원인을 직접 찾을 수 없으면 주위에 계측을 추가하여 문제에 대한 데이터를 수집하십시오. "명령에서이 버그를 재현 할 수 있다면 디버거에서 무엇을보고 싶은지"를 물어보고 기록하십시오. 문제를 더 잘 이해할 때까지 필요에 따라 반복하십시오. Doc Brown이 제안한대로 버그와 관련된 상태에 대한 로깅을 추가하십시오. 손상된 데이터를 감지하는 어설 션을 추가하십시오. 예를 들어, 버그가 응용 프로그램 충돌 인 경우 충돌 로깅 메커니즘을 추가하십시오. 이미 큰 로그가있는 경우 충돌 로그에 주석을 추가하여 충돌과 잠재적으로 관련된 상태를 기록하십시오. 동시성 문제가 관련되는지 여부를 고려하고 스레드 안전성을 테스트합니다 .

셋째, 탄력성. 버그는 불가피하므로 시스템을보다 탄력적으로 개선하여 버그로부터 쉽게 복구 할 수있는 방법을 스스로에게 물어보십시오. 백업을 개선 (또는 존재) 할 수 있습니까? 더 나은 모니터링, 장애 조치 및 경고? 더 많은 중복성? 더 나은 오류 처리? 종속 서비스를 서로 분리 하시겠습니까? 데이터베이스 액세스 및 수동 쿼리에 대한 프로세스를 향상시킬 수 있습니까? 기껏해야 이러한 것들이 버그의 결과를 덜 심각하게 만들고 최악의 경우 어쨌든 좋은 일이 될 것입니다.


5
  1. 가장 가능성이 큰 원인은 수동 데이터베이스 액세스 라고 생각한다고 프로젝트 관리자에게 설명하십시오 .
  2. 그래도이 문제를 일으킨 코드를 찾고자한다면 코드를 다시 살펴보십시오.
  3. 몇 시간 (또는 다른 적절한 시간)으로 돌아와서 이로 인해 발생한 코드를 찾을 수 없다고 말하면 여전히 가장 큰 원인은 수동 데이터베이스 액세스라고 생각합니다.
  4. 그들이 여전히 코드를 찾고자한다면 얼마나 시간을 할애 할 것인지 물어보십시오. 이 작업을 수행하는 동안 기능 X, 버그 Y 또는 개선 Z에서 작업하지 않을 것임을 미묘하게 상기시킵니다.
  5. 그들이 원하는만큼 시간을 보내십시오. 여전히 가장 큰 원인이 수동 데이터베이스 액세스라고 생각되면이를 알려주십시오.
  6. 그들이 경우 여전히 당신이 코드를보고 싶지이 명확 팀의 시간을 비생산적인 사용 상태가되어,이 문제를 제기.

향후 이러한 종류의 문제를 야기하는 수동 데이터베이스 액세스 가능성을 줄이기 위해 추가 프로세스를 추가해야하는지 고려할 수도 있습니다.


1
엔지니어 중 한 명이 수동 업데이트를 수행 한 것을 몰랐습니다. 엔지니어는 데이터베이스에서 직접 쿼리를 거의 실행하지 않습니다. 이것은 단지 일회성으로 잊어 버렸습니다. 우리는 하루 + 일주일 내내 무엇이 잘못되었는지 알아 내기 위해 준비했습니다. 내 질문은 원인을 찾을 수없고 잠재적 원인이 무엇인지 제안 할 수없는 경우 어떻게됩니까?
Nik Kyriakides

5
"내 질문은 원인을 찾을 수없고 잠재적 원인이 무엇인지 제안 할 수없는 경우 어떻게됩니까?"이것이 바로 '고칠 수 없습니다-복제 할 수 없습니다'플래그가 발명 된 정확한 이유입니다.
esoterik

4

고객이 데이터베이스가 손상되었다고보고했을 때 메인 프레임 데이터베이스 제품 개발 팀에서 일하고있었습니다. 디스크에서 비트의 내부 상태가 데이터베이스 소프트웨어를 통해 데이터베이스를 읽을 수 없다는 의미에서 손상이 발생했습니다. 메인 프레임 세계에서 고객은 당신에게 수백만 달러를 지불하고 있으며 이것을 진지하게 받아 들여야합니다. 이것이 우리가 한 일입니다.

0 단계 : 데이터베이스를 복구하여 고객이 다시 시작하고 실행하도록 도와줍니다.

1 단계 : 16 진수 수준으로 디스크의 파일을 검사하여 손상이 체계적인지 확인했습니다. 동일한 손상의 인스턴스가 여러 개있었습니다. 데이터베이스 소프트웨어 수준에서 발생했습니다. 실제로 멀티 스레딩 문제를 배제 할 수 있다고 생각한 것은 충분히 체계적이었습니다.

다른 많은 이론을 제거한 후에 데이터베이스의 물리적 재구성에 사용할 수있는 유틸리티를 사용했습니다. 올바른 수준에서 데이터에 액세스 할 수있는 유일한 코드 인 것 같습니다. 그런 다음 신중하게 선택된 옵션을 사용하여이 유틸리티를 실행하는 방법을 발견하여 문제를 재현했습니다. 고객은 이것이 자신이 한 일임을 확인하거나 거부 할 수 없었지만, 이것이 설명 할 수있는 유일한 설명 이었기 때문에 가능한 원인이라고 판단하고 진단을 받아 들일 수밖에 없었습니다. .

2 단계 : 그런 다음 소프트웨어를 다음과 같이 두 가지로 변경했습니다. (a) "내가하는 일을 알고 있습니다"사용자 인터페이스를 통해 실수로이 효과를 발생시키기 어렵게 만들고 (b) 새 로그 파일을 도입하여 다시 한 번, 우리는 사용자 행동에 대한 기록을 가질 것입니다.

따라서 기본적으로 (a) 손상을 복구하고 라이브 러닝을 복원합니다. (b) 근본 원인을 찾고 (c) 다시 발생하는 것을 방지하거나 다시 발생하는 경우 쉬운 진단을 수행하는 데 필요한 모든 작업을 수행합니다.


3

내 경험상 당신의 상사가 원하는 것은 이것이 재발하지 않을 것이라는 수준의 확신입니다. 코드가 원인이 아닌 경우, 단일 테스트를 통해 보장되므로 코드베이스에서 이미 테스트 적용 범위를 가지고 있다고 가정하면 솔루션은 데이터베이스에 "테스트"를 추가해야합니다. 나는 돈 길먼을 인용 할 것이다.

프로덕션 데이터베이스에는 전체 액세스 로깅 및 역할 기반 액세스 제어가 있어야합니다. 따라서 WHO가 데이터베이스에 대해 무엇을했는지에 대한 확실한 증거가 있어야 코드에서주의하지 않은 운영 보안으로 관심을 이동시킬 수 있습니다.

또한 생산 데이터 변경에 대한 표준 운영 절차가 있어야합니다. 예를 들어, DBA는 데이터를 변경하지 않아야하고 개발자는 변경을 스스로 실행하지 않아야하며 SOP에 정의 된대로 서로간에 공식적으로 메일 또는 티켓 변경을 요구해야합니다.

어딘가에 나를 인용 할 수 없다면 어딘가에 이와 같은 인용문이 있어야합니다.

요리사가 화장실 청소 책임자가 아닌 완벽한 이유가 있습니다.


1

재현 할 수없는 버그로 수행해야하는 몇 가지가 있습니다.

  1. 티켓을 만듭니다

티켓을 만들고 티켓에서 생각할 수있는 모든 것을 기록하십시오. 또한이 "버그"가 이전에 기록되었는지 확인하고 티켓을 서로 연결하십시오. 결국 버그를 재현하는 방법에 대한 패턴을 설정하기에 충분한 티켓을 얻을 수 있습니다. 이를 피하기 위해 사용되는 임시 해결책이 포함됩니다. 이것이 유일한 경우라도, 처음이 있다면 결국 두 번째가 될 것입니다. 원인을 찾은 경우 원인이 무엇인지 설명으로 티켓을 닫아 다시 발생하면 어떤 일이 있었는지에 대한 강력한 아이디어를 얻습니다 (잘못된 병합에서 수정 사항이 손실 됨)

  1. 강화 분석 수행

시스템, 실패한 내용 및 실패한 방법을보십시오. 고장 가능성을 줄이기 위해 업데이트 할 수있는 코드 영역을 찾으십시오. 몇 가지 예 ...

  • 임시 코드를 전용 통화 (예 execute(<query>):executeMyStoredProcedure(<params>)
  • 야간 확인 스크립트를 실행하여 데이터 무결성을 확인합니다 (다음에 24 시간 내에이를 감지 할 수 있도록)
  • 로깅 및 보관을 추가 / 개선합니다 (백업).
  • 부적절한 보안 제한 변경 (예 : 데이터 만 읽는 사람 / 프로그램은 쓰기 권한이 없으며 프로덕션을 담당하지 않는 개발자는 프로덕션 서버에 로그인 할 수 없음)
  • 누락 된 데이터 확인 / 위생 추가

이렇게하면 버그가 해결되지는 않지만 그래도 버그가 해결되지 않으면 시스템이 더 안정적 / 보안 적이므로 여전히 효과가 있습니다.

  1. 시스템 경고 추가

2의 일부이지만 문제가 발생했으며 다시 언제 발생하는지 알아야합니다. 시스템을 모니터링 할 수있는 상태 점검 스크립트 / 프로그램을 작성하여 버그 재 포장 후 24 시간 이내에 관리자에게 경고 할 수 있습니다 (지연 시간이 짧을수록 더 좋을 수 있습니다). 이렇게하면 정리가 훨씬 쉬워집니다. (데이터베이스의 로그 외에도 OS는 로그하는 사람과 수행하는 비 읽기 작업을 로깅해야합니다. 최소한 해당 머신에 대한 트래픽의 네트워크 로그가 있어야합니다)


0

문제는 소프트웨어의 결함이 아니라 데이터베이스를 조작하는 사람에 의한 것입니다. 문제를 "버그"라고 부르면 버그를 쉽게 재현 할 수 있습니다. 누군가가 데이터베이스에 어리석은 일을 할 때 항상 문제가 발생합니다. 데이터베이스를 수동으로 수정하거나 테스트하지 않은 소프트웨어를 사용하지 않고 데이터베이스를 수정할 수있는 사람을 엄격하게 제어하여이 "버그"를 피할 수있는 방법이 있습니다.

데이터베이스의 결함 만 "버그"라고 부르면 재현 할 수없는 버그가없고 전혀 버그가없는 것입니다. 버그 리포트가있을 수 있지만 버그로 인한 문제가 아니라는 증거도 있습니다. 따라서 "복구 할 수없는"것이 아니라 "손상된 데이터베이스"와 같은 버그 보고서를 닫을 수 있습니다. 조사에 버그가 없음을 나타내는 버그 보고서가있는 것은 드문 일이 아니지만 사용자가 소프트웨어를 잘못 사용했거나 사용자의 기대가 잘못되었습니다.

이 경우에도 반복하고 싶지 않은 문제가 있다는 것을 알고 있으므로 첫 번째 경우와 동일한 조치를 취하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.