Manejo de errores no reproducibles

73

Supongamos que su equipo escribe un sistema de software que (¡sorprendentemente!) Funciona bien.

Un día, uno de los ingenieros ejecuta por error algunas consultas SQL que cambian algunos de los datos de la base de datos y luego se olvida de ello.

Después de un tiempo descubres los datos corruptos / erróneos y todos se rascan la cabeza sobre qué parte del código causó esto y por qué, sin éxito. Mientras tanto, el gerente del proyecto insiste en que encontremos la parte del código que lo causó.

Como tratas con esto?

Nik Kyriakides
fuente
32
Si el ingeniero lo olvidó, ¿cómo sabe que eso fue lo que sucedió? ¿Cómo fue corrompido por alguien que ejecuta un script, y no por un error?
DaveG
18
Tuvo una epifanía después de un día o dos. Esto es hipotético en caso de que nunca recordara cuál podría haber sido fácilmente el caso.
Nik Kyriakides
12
Esto es hipotético. Estoy seguro de que el primer ministro nos haría perseguir esto, tanto como podamos si él nunca lo recordara. Sé que lo haría.
Nik Kyriakides
59
xkcd.com/583 ;) [lenguaje NSFW]
Baldrickk
100
"Supongamos que su equipo escribe un sistema de software que funciona bien". ¡Deja de molestarme con fantasías imposibles!
Paul D. Waite

Respuestas:

134

Es obvio que ningún gerente de proyecto invertirá una cantidad infinita de tiempo en tal problema. Quieren evitar que la misma situación ocurra nuevamente.

Para lograr este objetivo, incluso si uno no puede encontrar la causa raíz de tal falla, a menudo es posible tomar algunas medidas para

  • Detecta tales fallas antes en caso de que vuelvan a ocurrir
  • Hacer que sea menos probable que vuelva a ocurrir el mismo fallo
  • Haga que el sistema sea más robusto frente al tipo específico de inconsistencia

Por ejemplo, un registro más detallado, un manejo de errores más detallado o una señalización de error inmediata podrían ayudar a evitar que se repita el mismo error o encontrar la causa raíz. Si su sistema permite agregar disparadores de base de datos, tal vez sea posible agregar un disparador que prohíba la inconsistencia que se introduce en primer lugar.

Piense cuál podría ser el tipo de acción apropiado en su situación y sugiérale esto al equipo; Estoy seguro de que su gerente de proyecto estará encantado.

Un día, uno de los ingenieros ejecuta por error algunas consultas SQL que cambian algunos de los datos de la base de datos y luego se olvida de ello.

Como lo mencionaron otros, también es una buena idea prohibir dicho procedimiento (si tiene influencia sobre cómo se opera el sistema). Nadie debe poder ejecutar consultas ad-hoc no documentadas que cambien el contenido de la base de datos. Si es necesario realizar dicha consulta, asegúrese de que exista una política para almacenar la consulta junto con su fecha de ejecución, el nombre de la persona que la ejecutó y la razón por la que se utilizó, en un lugar documentado.

Doc Brown
fuente
8
@NicholasKyriakides Probablemente ambos. Todas estas son medidas de sentido común para simplificar la depuración "diferida". Probablemente han sido escritos en innumerables procedimientos.
Nic Hartley
29
De vez en cuando sucede que tiene algún tipo de problema grave en un sistema de producción y no puede determinar la causa a pesar de un esfuerzo significativo. En última instancia, lo atribuye a los rayos cósmicos e intenta mejorar la información (por lo que si vuelve a ocurrir, tendrá una mejor oportunidad de encontrar la causa) y la mitigación (por lo que si vuelve a ocurrir, el daño será mínimo) y vea si se repite
David Schwartz
2
@Nicholas Kyriakides: experiencia personal durante varias décadas.
Doc Brown
44
También debe tenerse en cuenta que es muy posible que, incluso si hubiera un error, ya no esté allí. Lo mejor que puede hacer a veces es corregir los datos y mejorar las pruebas / procedimientos para asegurarse de que el mismo problema no vuelva a ocurrir.
kutschkem
2
Encontrar problemas intermitentes se trata de iniciar sesión y encontrar un punto de estrangulamiento que pueda detectarlos a medida que ocurren, luego caminar hacia atrás desde allí para identificar la fuente. A veces se requieren cosas desagradables como desencadenantes, o la implementación de código con registro de errores ruidoso, solo para tener una idea de cuándo / dónde del error.
AaronLS
51

Esto no es un error

Al menos no en tu código. Es un error en tu proceso . Su gerente de proyecto debería estar mucho más preocupado por su proceso que su código.

Como tratas con esto?

En pocas palabras, al no permitir que los ingenieros cambien las bases de datos de producción o desarrollo compartido .


Suponiendo que se trata de una base de datos de desarrollo compartida:

Idealmente, si es posible, evite tener una base de datos compartida en primer lugar . En cambio, tenga bases de datos por desarrollador que sean de corta duración. Esto debería automatizarse con scripts, de lo contrario el costo de la prueba se vuelve demasiado grande, y hay un incentivo para no probar las cosas. Puede tener estas bases de datos en la estación de trabajo del desarrollador o en un servidor central.

Si, por alguna razón, DEBE tener una base de datos compartida, debe usar accesorios , esencialmente, algo que establece la base de datos en un estado bueno conocido cada vez que necesita usarla. Esto evita que los desarrolladores sean mordidos por los cambios de otras personas.

Si necesita aplicar cambios permanentes a la base de datos, debe confirmarlos en su control de origen . Configure su base de datos de modo que los desarrolladores no tengan permiso para escribir directamente en ella, y tengan un programa que extraiga los cambios del control de origen y los aplique.

Finalmente, a partir de su descripción de cómo está depurando cosas, parece que no está usando CI . Use CI . Es un poco difícil de configurar, pero ahorrará MUCHO tiempo a largo plazo, sin mencionar que evitará que se preocupe por los errores de base de datos no reproducibles. ¡ Ahora solo tendrás que preocuparte por los heisenbugs !


Asumiendo que esta es una base de datos de producción:

Si sus desarrolladores están cambiando las bases de datos de producción, muchas cosas han salido terriblemente mal, incluso si los cambios son absolutamente correctos.

Los desarrolladores nunca deberían acceder a las bases de datos de producción . No hay absolutamente ninguna razón para hacerlo, y tantas cosas que pueden salir muy, muy mal.

Si necesita arreglar algo en una base de datos de producción, primero haga una copia de seguridad, restaure esa copia de seguridad en una instancia (de desarrollo) diferente y luego juegue alrededor de esa base de datos de desarrollo. Una vez que cree que tiene una solución lista (¡en el control de origen!), Vuelve a hacer la restauración, aplica la solución y ve el resultado. Luego, después de hacer una copia de seguridad de las cosas nuevamente (e idealmente evitar las actualizaciones simultáneas), arregla la instancia de producción, idealmente a través de un parche de software.

Si necesita probar algo en una base de datos de producción ... no, no lo necesita . Cualquier prueba que necesite hacer, debe hacerlo en una instancia de desarrollo. Si necesita algunos datos para hacer las pruebas, obtendrá esos datos allí.

goncalopp
fuente
12
Entonces, ¿su solución recomendada es viajar en el tiempo?
Benubird
77
Aunque esta es una solución decente para el ejemplo dado, la pregunta tiene un contexto mucho más general de tratar con errores que no se pueden reproducir y los administradores que quieren que persigan estos. Eso puede aplicarse a mucho más que solo problemas de bases de datos y administración de permisos. Siento que esta respuesta en realidad no responde la pregunta deseada, solo el ejemplo dado.
Kyle Wardle
@KyleWardle De acuerdo. Creo que la respuesta de Doc Brown cubre bastante bien el caso general (registro detallado y manejo de errores, condiciones de guardia). Principalmente agregué el mío porque vi que nadie había mencionado las fallas del proceso que condujeron al problema en primer lugar
goncalopp
2
@Benubird Creo que la respuesta se reduce a "la forma en que lidias con esto es evitar que vuelva a suceder". No creo que pueda "resolver" una base de datos de producción corrupta desde una perspectiva de ingeniería de software.
goncalopp
1
No va a cambiar el código para poner datos en la base de datos de desarrollo. En todos los lugares donde he trabajado, incluidas las grandes corporaciones, los desarrolladores tienen libertad para insertar datos de prueba y utilizar las mismas credenciales que usa la aplicación.
David Conrad
13

Una base de datos de producción debe tener un registro de acceso completo y controles de acceso basados ​​en roles. Por lo tanto, debe tener pruebas contundentes de que la OMS hizo QUÉ CUÁNDO en la base de datos y, por lo tanto, desvió la atención del código a una seguridad operativa deficiente.

Don gilman
fuente
2
Parece que es posible que no sepan exactamente cuándo ocurrió la corrupción de datos, lo que podría dificultar la tarea de averiguar qué registros deben investigar.
Nathanael
3
Desafortunadamente, al rastrear uno de estos descubrimos que también estaba destrozando los registros. (Sí. El error era real.)
Joshua
El registro combinado con los trabajos programados que verifican la integridad de los datos, aunque solo sea de la noche a la mañana, significa que los problemas se pueden marcar antes y resolver. Si quiere ser realmente cuidadoso, requiera una revisión por pares para los cambios.
Keith
En todos los lugares donde he trabajado, los desarrolladores se conectan a la base de datos con las mismas credenciales que usa la aplicación, por lo que el registro de acceso solo se mostrará cuando esa identificación haya realizado el cambio, no es que lo haya hecho un humano en lugar de un programa. Supongo que podría comparar la marca de tiempo con los registros de la aplicación para ver si la aplicación estaba haciendo algo que escribiría en la base de datos en ese momento.
David Conrad
@DavidConrad: ¿Por qué los desarrolladores tienen acceso a las credenciales que la aplicación usa en producción? Debería utilizar algún tipo de gestión secreta para que esas credenciales ni siquiera puedan leerse, excepto por su cuenta de servicio de aplicaciones, desde los servidores de aplicaciones de producción.
Daniel Pryden
6

En este caso, finalmente descubriste la causa, pero tomando tu hipótesis de que no ...

Primero, analiza lo que cambió. Si el sistema funcionaba bien antes, una mirada cuidadosa a todo lo que se ha hecho recientemente podría revelar el cambio que causó el error. Revise sistemáticamente su control de versiones, los sistemas de CI / implementación y el control de configuración para ver si algo cambió. Ejecute git bisect o un mecanismo equivalente para realizar una búsqueda binaria. Revise los registros. Busca registros que no sabías que tenías. Hable con todos los que tengan acceso al sistema para ver si han hecho algo recientemente. Para su problema, si es lo suficientemente exhaustivo en este proceso, es de esperar que esto revele las consultas SQL olvidadas.

En segundo lugar, la instrumentación. Si no puede encontrar directamente la causa de un error, agregue instrumentación a su alrededor para recopilar datos sobre el problema. Pregúntese "si pudiera reproducir este error en el comando, qué me gustaría ver en el depurador", y luego registre eso. Repita según sea necesario hasta que comprenda mejor el problema. Como sugiere Doc Brown, agregue el registro de estados relevantes para el error. Agregue aserciones que detecten datos corruptos. Por ejemplo, si su error es un bloqueo de la aplicación, agregue un mecanismo de registro de bloqueo. Si ya tiene uno, excelente, agregue anotaciones a los registros de fallas para registrar el estado potencialmente relevante para la falla. Considere si los problemas de concurrencia pueden estar involucrados y pruebe para ejercer seguridad de subprocesos .

Tercero, la resiliencia. Los errores son inevitables, así que pregúntese cómo puede mejorar sus sistemas para que sean más resistentes para que la recuperación del error sea más fácil. ¿Podrían sus respaldos ser mejorados (o existentes)? ¿Mejor monitoreo, conmutación por error y alertas? ¿Más redundancia? ¿Mejor manejo de errores? ¿Desacoplar los servicios dependientes entre sí? ¿Puede mejorar sus procesos de acceso a la base de datos y consultas manuales? En el mejor de los casos, estas cosas harán que las consecuencias de su error sean menos graves, y en el peor de los casos, probablemente sean buenas cosas para hacer de todos modos.

Zach Lipton
fuente
5
  1. Explique a su gerente de proyecto que cree que la causa más probable es el acceso manual a la base de datos.
  2. Si todavía quieren que busque el código que causó esto, vaya y eche otro vistazo al código.
  3. Regrese en un par de horas (u otro momento apropiado) y diga que no puede encontrar ningún código que haya causado esto, por lo tanto, todavía cree que la causa más probable es el acceso manual a la base de datos.
  4. Si todavía quieren que busque el código, pregúnteles cuánto tiempo les gustaría que dediquen a esto. Sutilmente recuérdeles que no estará trabajando en la función X, error Y o mejora Z mientras lo hace.
  5. Pase todo el tiempo que le pidan. Si aún cree que la causa más probable es el acceso manual a la base de datos, dígales esto.
  6. Si todavía quieren que busque el código, aumente el problema, ya que claramente se ha convertido en un uso improductivo del tiempo de su equipo.

También puede considerar si debe agregar procesos adicionales para reducir la probabilidad de que el acceso manual a la base de datos cause este tipo de problema en el futuro.

Philip Kendall
fuente
1
No tenía idea de que uno de los ingenieros realizó una actualización manual + los ingenieros casi nunca ejecutan consultas directamente en la base de datos. Este simplemente lo hizo, como algo excepcional y se olvidó de eso. Pasamos un día + preparándonos para pasar una semana completa descubriendo lo que está mal. Mi pregunta es qué sucede si no puede encontrar la causa y no puede sugerir cuál podría ser la causa potencial.
Nik Kyriakides
55
"Mi pregunta es qué sucede si no puede encontrar la causa y no puede sugerir cuál podría ser la causa potencial" Esta es la razón exacta por la que se inventó la bandera 'no se solucionará, no se puede duplicar'.
esoterik
4

Estaba trabajando en el equipo de desarrollo para un producto de base de datos de mainframe cuando un cliente informó que tenía una base de datos corrupta. Una corrupción en el sentido de que el estado interno de los bits en el disco significaba que la base de datos no era legible a través del software de la base de datos. En el mundo mainframe, los clientes le pagan $ millones y usted debe tomar esto en serio. Esto es lo que hicimos:

Paso 0: ayude al cliente a ponerse en funcionamiento nuevamente reparando la base de datos.

Paso 1: al examinar el archivo en el disco a nivel hexadecimal, determinamos que la corrupción era sistemática: hubo muchos casos de la misma corrupción. Entonces, definitivamente fue causado a nivel del software de base de datos. De hecho, fue lo suficientemente sistemático como para sentir que podíamos descartar problemas de subprocesos múltiples.

Después de eliminar muchas otras teorías, nos centramos en una utilidad que podría usarse para la reorganización física de la base de datos. Parecía ser el único código que tenía acceso a los datos en el nivel correcto. Luego descubrimos una forma de ejecutar esta utilidad, con opciones cuidadosamente seleccionadas, que reproducían el problema. El cliente no pudo confirmar o negar que esto era lo que había hecho, pero como era la única explicación que podíamos encontrar, decidimos que era la causa probable y no tenían más remedio que aceptar nuestro diagnóstico. .

Paso 2: Luego hicimos dos cambios en el software: (a) dificultó causar este efecto accidentalmente a través de una interfaz de usuario "sí, sé lo que estoy haciendo", y (b) introdujo un nuevo archivo de registro para que si Si alguna vez sucedió de nuevo, tendríamos un registro de las acciones del usuario.

Entonces, básicamente (a) repara el daño y restaura la ejecución en vivo, (b) encuentra la causa raíz, (c) haz lo que sea necesario para evitar que vuelva a ocurrir o para facilitar el diagnóstico si vuelve a ocurrir.

Michael Kay
fuente
3

Desde mi experiencia, lo que su jefe quiere es cierta garantía de nivel de que esto no volverá a ocurrir. Si es el caso de que la causa no fue el código, porque eso está asegurado por la prueba de unidad, por lo que suponiendo que ya tenga cobertura de prueba en su base de código, la solución debería agregar "prueba" a su base de datos. Citaré a Don Gilman, porque él clavó allí:

Una base de datos de producción debe tener un registro de acceso completo y controles de acceso basados ​​en roles. Por lo tanto, debe tener pruebas contundentes de que la OMS hizo QUÉ CUÁNDO en la base de datos y, por lo tanto, desvió la atención del código a una seguridad operativa deficiente.

Pero también, debe tener un Procedimiento operativo estándar para cambiar los datos en producción. Por ejemplo, ningún DBA debe cambiar los datos, ningún desarrollador debe ejecutar el cambio por sí mismo y, como se define en el SOP, deben exigirse mutuamente formalmente el cambio por correo o boleto.

Debe haber una cita como esta en alguna parte, si no, puede citarme:

Hay una razón perfectamente buena para que los chefs no sean los responsables de limpiar los inodoros.

CesarScur
fuente
1

Hay varias cosas que se deben hacer con errores no reproducibles.

  1. Crea un boleto para ello

Cree un boleto y registre todo lo que pueda pensar en el boleto. Compruebe también si este "error" se ha registrado antes y vincule los tickets. Eventualmente, puede obtener suficientes tickets para establecer un patrón sobre cómo reproducir el error. Esto incluye soluciones alternativas utilizadas para tratar de evitarlo. Incluso si esta es la única instancia, si hay una primera vez, eventualmente habrá una segunda vez. Cuando encuentre la causa, cierre el ticket con una explicación de cuál fue la causa para tener una idea clara de lo que sucedió si vuelve a ocurrir (solución perdida en una fusión incorrecta)

  1. Haz un análisis de endurecimiento

Mire el sistema, qué falló y cómo falló. Intente encontrar áreas del código que puedan actualizarse para que la falla sea menos probable. Algunos ejemplos...

  • Reemplace el código ad-hoc con una llamada dedicada (como execute(<query>)conexecuteMyStoredProcedure(<params>)
  • Ejecute scripts de verificación nocturnos para verificar la integridad de los datos (para que esto pueda detectarse dentro de las 24 horas la próxima vez)
  • Agregar / mejorar el registro y el archivo (copia de seguridad).
  • Cambie los límites de seguridad inadecuados (por ejemplo, las personas / programas que solo leen datos no tienen permiso de escritura; no permiten que los desarrolladores que no son responsables de la producción puedan iniciar sesión en los servidores de producción)
  • Agregar verificación de datos / saneamiento donde faltan

Es posible que esto no solucione el error, pero incluso si no lo hace, el sistema ahora es más estable / seguro, por lo que aún vale la pena.

  1. Agregar alertas del sistema

Parte de 2, pero sucedió algo y debes saber cuándo sucede de nuevo. Debe crear algunos scripts / programas de comprobación de estado para supervisar el sistema, de modo que los administradores puedan recibir alertas dentro de las 24 horas posteriores a la aparición del error (cuanto menos demora, mejor, dentro de lo razonable). Esto hará que la limpieza sea mucho más fácil. (Tenga en cuenta que, además de los registros de las bases de datos, el sistema operativo también debe registrar quién inicia sesión en él y cualquier acción no leída que realicen. Al menos, debe haber registros de tráfico de red a esa máquina)

Tezra
fuente
0

Su problema no fue causado por una falla en su software, sino por alguien que estaba jugando con la base de datos. Si llama a las cosas que van mal un "error", entonces su error es fácilmente reproducible: las cosas siempre saldrán mal cuando alguien hace cosas estúpidas en la base de datos. Y hay formas de evitar este "error", al no permitir que la base de datos se modifique manualmente o mediante el uso de software no probado, y al controlar estrictamente quién puede modificar la base de datos.

Si solo llama "error" a las fallas de su base de datos, entonces no tiene un error irreproducible, no tiene ningún error. Es posible que tenga un informe de error, pero también tiene evidencia de que el problema no fue causado por un error. Por lo tanto, puede cerrar el informe de error, no como "irreproducible", sino como "base de datos dañada". No es raro tener informes de errores donde la investigación muestra que no hay errores, pero un usuario usó mal el software, las expectativas del usuario eran incorrectas, etc.

En ese caso, todavía sabe que hubo un problema que no desea que se repita, por lo que debe realizar la misma acción que en el primer caso.

gnasher729
fuente