¿Cómo se evalúan las condiciones de carrera en una base de datos?

30

Intento escribir el código de la base de datos para asegurarme de que no esté sujeto a condiciones de carrera, para asegurarme de que he bloqueado las filas o tablas correctas. Pero a menudo me pregunto: ¿es correcto mi código? ¿Es posible forzar que se manifiesten las condiciones de carrera existentes? Quiero asegurarme de que si suceden en un entorno de producción, mi aplicación hará lo correcto.

En general, sé exactamente qué consulta simultánea puede causar un problema, pero no tengo idea de cómo obligarlos a ejecutarse simultáneamente para ver si ocurre el comportamiento correcto (por ejemplo, usé el tipo correcto de bloqueo), que los errores correctos son arrojado, etc.

Nota: Uso PostgreSQL y Perl, por lo que si esto no se puede responder genéricamente, probablemente debería volver a etiquetarse como tal.

Actualización: preferiría que la solución fuera programática. De esa manera puedo escribir pruebas automatizadas para asegurarme de que no haya regresiones.

xenoterracida
fuente
¿Por "condición de carrera" quieres decir "punto muerto"?
Cayo
2
@Gaius ... no, aunque creo que es un posible resultado de algunas condiciones de carrera
xenoterracide
Las condiciones de carrera de @Gaius en una base de datos estarían haciendo cosas como soltar una tabla antes de crearla o actualizar una fila antes de insertarla. En general, me imagino que es manejado por la lógica de la aplicación fuera de la base de datos.
Mark D
actualizar una fila antes de que se haya insertado? eso no causaría un problema de db. ninguna condición de carrera sería como buscar una fila y actualizarla, pero que otro usuario la actualice después de que se recupere su fila pero antes de que se procese su actualización.
xenoterracide
1
@MarkD - No. Hay muchos tipos de condiciones de carrera que surgen de encapsular incorrectamente una unidad atómica de trabajo en su base de datos. Aquí hay un ejemplo. Recuerde, "una condición de carrera o peligro de carrera es una falla en un sistema o proceso electrónico por el cual la salida o el resultado del proceso depende inesperada y críticamente de la secuencia o el momento de otros eventos ". ( fuente )
Nick Chammas

Respuestas:

11

Lo hago todo el tiempo con mis módulos T-SQL.

Esencialmente, todo lo que necesita hacer es ejecutar sus módulos desde dos o más conexiones en un bucle durante un par de minutos . Por lo general, todos los problemas potenciales se exponen en unos minutos, suponiendo que tenga una caja de SQL Server con CPU decentes.

Escribí algunos ejemplos aquí y aquí .

Alaska
fuente
4

Por lo general, trabajo con la herramienta de línea de comandos del RDBMS, solo teniendo 2 (o más) instancias de la CLI iniciadas. Luego puede reproducir uno por uno y como una carrera (que se vería como un RPG de acción) las declaraciones SQL que envía su capa de aplicación. Debe experimentar / sentir los sistemas de bloqueo en acción ya que su CLI se "colgará" un poco, esperando que los bloqueos se liberen de la otra CLI.

Si esto suena claro como el barro, no dudes en decirlo ;-)

Julien
fuente
¿podrías dar un ejemplo paso a paso? ¿Pueden escribirse pruebas programáticas para hacer lo mismo?
xenoterracide
1

Las condiciones de carrera requieren múltiples hilos de ejecución, por lo tanto, para realizar una prueba unitaria, deberá poder iniciar uno o más hilos. En Oracle, usaría DBMS_Scheduler para ejecutar un proceso para simular un segundo usuario. Si PostgreSQL / Perl tiene una manera de iniciar un segundo proceso mediante programación, entonces debería poder hacer algo como esto:

Proceso 1 Proceso 2

Iniciar proceso 2. >>                            
Retrasar para permitir que 2 haga su trabajo. 
. Bloquee filas o cambie datos.
. Retrasar para permitir que 1 haga su trabajo.
Intente bloquear filas o cambiar datos. .
Verifique que se realice el manejo adecuado. .
Termina .
                                                Termina

Es bueno ver pensar en cómo manejar las condiciones de carrera y, lo que es más importante, cómo probarlas en la unidad.

Leigh Riffel
fuente
No describiría tales pruebas como pruebas unitarias, porque las pruebas unitarias deben ejecutarse exactamente de la misma manera cada vez. Las condiciones de carrera fallan en los procesos involucrados de manera intermitente, no exactamente de la misma manera cada vez.
AK
@AlexKuznetsov Tienes razón en que las condiciones inesperadas de la carrera pueden mostrarse de forma intermitente, sin embargo, el OP se refiere a las condiciones esperadas que él cree que está manejando el código. Estas condiciones específicas pueden reproducirse con precisión y el manejo puede verificarse con una prueba unitaria.
Leigh Riffel
-2

Siempre que bloquee las filas, no debería estar en condiciones de carrera, ya que eso generalmente se produce cuando no hay un bloqueo en su lugar.

Pero podría quedar bloqueado si una pregunta bloquea su pregunta por demasiado tiempo.

Esto es difícil de probar ya que el tiempo para las consultas puede cambiar cuando la base de datos crece.

Las consultas que funcionan bien con 100 000 filas de datos de prueba salen del gráfico con 10 000 000 filas.

Este tipo de problema puede ser muy difícil de encontrar por adelantado, pero muchos DB tienen algún método para identificar consultas lentas.

Al usar ese sistema regularmente, debería ser capaz de atrapar cualquier consulta que surja en problemas con una amplia advertencia.

Si trabajas por tu cuenta, es otra historia, pero no puedo evitarlo.

Nick Chammas
fuente
@darioo lol, pensé que tal vez wn era un acrónimo de algo ... no sé qué querría decir con "bloquear por tu cuenta". Si quiere decir que no con un ORM, verifiqué el código que mi ORM genera, ciertamente no funciona. bloqueo a la derecha. Esa es una de las razones por las que me gustaría poder probar el posible escenario de condición de carrera.
xenoterracida
Sí, quise decir propio, y normalmente el controlador de la base de datos maneja el bloqueo, la fila, la tabla o posiblemente el campo, pero solo estoy abriendo la posibilidad de que use algún DB que no maneje el bloqueo;)
.. Estoy bastante seguro de que si tengo una transacción de extracto múltiple, mi DB no sabrá qué filas bloquear automáticamente ... cosas como select for update si no existieran si lo hicieran ...
xenoterracide