¿Debo bloquear filas en mi base de datos en la nube mientras un usuario las está editando?

12

Estoy creando una aplicación de escritorio que persiste los datos en la nube. Una de las preocupaciones que tengo es comenzar a editar un elemento en la aplicación y dejarlo por un tiempo haciendo que los datos se vuelvan obsoletos. Obviamente, esto también puede suceder si 2 personas intentan editar el mismo elemento al mismo tiempo. Cuando terminen su edición y quieran guardar los datos, necesitaría sobrescribir lo que existe actualmente en la base de datos o verificar que comenzaron a editar después del último cambio y forzarlos a descartar sus cambios o quizás darles la opción de arriesgarse sobrescribir los cambios de otra persona.

Pensé en agregar campos is_lockedy lock_timestampen la tabla DB. Cuando un usuario comienza a editar el elemento, la fila cambiará is_lockeda verdadero y establecerá la marca de tiempo de bloqueo a la hora actual. Entonces tendría algo de tiempo durante el cual se mantiene el bloqueo (por ejemplo, 5 minutos). Si alguien más intenta editar el elemento, recibirá un mensaje que dice que el elemento está bloqueado y cuando el bloqueo caduca automáticamente. Si el usuario se retira mientras edita, el bloqueo expirará automáticamente después de un período de tiempo relativamente corto y una vez que lo haga, se le advertirá al usuario que el bloqueo ha expirado y se verá obligado a reiniciar la edición después de que se actualicen los datos.

¿Sería este un buen método para evitar sobrescribir datos obsoletos? Es excesivo (no espero que la aplicación sea utilizada por más de unas pocas personas al mismo tiempo en una sola cuenta).

(Otra preocupación que tengo es que 2 personas obtengan un candado para el mismo artículo, sin embargo, creo que es una condición de carrera con la que me siento cómodo).

yitzih
fuente
1
"Otra preocupación que tengo es que 2 personas obtengan un candado para el mismo artículo, sin embargo, creo que es una condición de carrera con la que me siento cómodo".
Jules
La mayoría de los motores de bases de datos (del tipo relacional, al menos) han incorporado soporte para esto. Es un concepto muy común en el mundo RDBMS, e incluso las bases de datos "de juguete" lo manejan lo suficientemente bien, dado que usted le dice que desea un bloqueo optimista o pesimista. De todos modos, no creo que sea algo que necesite construir de ninguna manera: verifique las opciones en su motor de base de datos para ver cómo trabajar con él.
jleach
El hecho de que su aplicación sea una aplicación de escritorio (un cliente pesado ) no hace mucha diferencia. Se puede diseñar de la misma manera que una aplicación de servidor de varias instancias de alta disponibilidad.
Hosam Aly

Respuestas:

19

Una cosa que te ayudará aquí es la terminología. Lo que estás describiendo aquí se llama 'bloqueo pesimista'. La principal alternativa a este enfoque es el 'bloqueo optimista'. En el bloqueo pesimista, cada actor debe bloquear el registro antes de actualizarlo y liberar el bloqueo cuando se complete la actualización. En el bloqueo optimista, asume que nadie más está actualizando el registro y lo intenta. La actualización falla si el registro fue cambiado por algún otro actor.

El bloqueo optimista generalmente es preferible si la posibilidad de que dos actores actualicen la misma cosa al mismo tiempo es baja. Pesimista se usa generalmente cuando la probabilidad es alta o si necesita saber que su actualización podrá tener éxito antes de comenzar. En mi experiencia, el bloqueo optimista es casi siempre preferible porque hay muchos problemas inherentes al bloqueo pesimista. Una de las cuestiones más importantes se aborda en su pregunta. Los usuarios pueden bloquear un registro para editarlo y luego irse a almorzar. Su mitigación ayudará con eso, pero la experiencia del usuario no será mejor que el enfoque optimista y es probable que sea mucho peor. Por ejemplo, un usuario abre un registro, comienza a actualizarlo y su jefe aparece en su escritorio. Otro usuario intenta editar el registro. Está cerrada. El segundo usuario sigue intentando y después de 5 minutos, el bloqueo caduca y el segundo usuario actualiza el registro. El primer usuario vuelve a la pantalla, intenta guardar y se le dice que perdió su bloqueo. Ahora, en el mismo escenario con todo igual, excepto el uso de un bloqueo optimista, la experiencia del primer usuario es prácticamente la misma, pero el segundo usuario no espera 5 minutos.

El esquema que diseñe mejoraría enormemente implementando un bloqueo optimista para el valor de bloqueo, pero mi presentimiento es que el bloqueo optimista probablemente esté bien para todo y puede deshacerse del campo is_locked.

No proporciona qué 'base de datos en la nube' está utilizando. Probablemente debería examinar las características de eso para ver si hay características integradas para esto antes de implementar su propia solución.

Aquí está la receta básica: en lugar de un campo is_locked, tenga un campo de número de versión. Cuando recupera el registro, extrae la versión actual del registro. Cuando actualiza, hace que la actualización dependa del campo de versión que coincida con lo que recuperó y lo incremente en caso de éxito. Si la versión no coincide, la actualización no tiene efecto y usted la informa como un error.

JimmyJames
fuente
Esta es una respuesta muy útil. ¿Puede explicar por qué se desalienta el bloqueo pesimista cuando hay una pequeña posibilidad de "colisiones"? ¿Es simplemente porque requiere ir a la base de datos para comenzar a editar, o por una complejidad adicional u otra razón? ¡Gracias!
Yitzih
3
@yitzih Algunas lecturas sugeridas: Fowler et al, Patterns of Enterprise Application Architecture . Hay un capítulo completo sobre esta cuestión, con una buena discusión de todas las opciones y razones para elegirlas.
Jules
2
@ Jimmy - Tu respuesta está bien. En algunos casos, informar un error no puede ser suficiente. Considere un caso en el que un usuario pasa unos minutos actualizando un registro. En ese caso, simplemente fallar puede no ser lo suficientemente bueno, uno puede querer darle al usuario la oportunidad de fusionar sus cambios durante el vuelo con los cometidos por el otro usuario. Debería haber dicho que el bloqueo optimista puede requerir la resolución de conflictos dependiendo de sus requisitos.
Jon Raynor
3
Vale la pena mencionar que el bloqueo pesimista es mucho más fácil de explicar al cliente. Si escribe un mensaje de que el cliente no puede acceder al registro porque está siendo editado por otro, el cliente lo comprende muy bien y generalmente lo acepta. Si en cambio le dice al cliente después de guardar que guardar no fue posible porque ya fue actualizado por otro usuario, 7/10, el cliente se sentirá frustrado y / o esperará explicaciones para este extraño comportamiento del programa.
Neil
2
@Neil Eso es cierto y creo que a menudo es por eso que se usa el bloqueo pesimista cuando el optimismo es más apropiado. A menudo, el flujo de trabajo hace que sea muy poco probable que haya una colisión.
JimmyJames
0

De la respuesta de @ JimmyJames , podemos ver cómo la pregunta es realmente sobre la experiencia del usuario .

Todo depende del contexto. ¿Cuánto tiempo y esfuerzo lleva actualizar un registro? ¿Con qué frecuencia desean varios usuarios actualizar el mismo documento?

Por ejemplo, si sus usuarios suelen tardar unos segundos en actualizar el registro y hay poca contención, entonces el bloqueo optimista es probablemente el camino a seguir. En el peor de los casos, un usuario tendrá que pasar unos segundos más, tal vez hasta un minuto, para actualizar un documento.

Si su documento es muy polémico pero bien estructurado, tal vez pueda permitirles bloquear campos individuales en incrementos de 30 segundos, mostrando un temporizador o una notificación discreta para permitirles extender el bloqueo.

Sin embargo, si sus usuarios pasan una cantidad considerable de tiempo o esfuerzo, entonces debería considerar otros enfoques. ¿Su registro está bien estructurado? ¿Podría mostrar a los usuarios una comparación (una diferencia) entre la versión en el servidor y la versión que están tratando de guardar? ¿Puedes resaltar las diferencias? ¿Puedes dejar que fusionen los cambios? Piense en la experiencia que desea tener con sus herramientas de control de código fuente. ¡Realmente no quieres ser forzado a escribir todo ese código nuevamente!

Puede consultar Google Docs para obtener inspiración adicional. Quizás pueda mostrar a los usuarios una notificación de que se ha guardado una nueva versión. Quizás pueda mostrarles cuántas personas tienen abierto el registro para que puedan elegir regresar en un momento menos polémico.

Hosam Aly
fuente