2009-05-07 7 views
8

Tengo una aplicación web empresarial C# ASP.NET que se usa internamente. Un problema con el que nos encontramos al crecer es que el diseño original no tenía en cuenta la comprobación de concurrencia, por lo que ahora varios usuarios acceden a los mismos datos y sobrescriben los cambios de otros usuarios. Entonces, mi pregunta es: para las webapps, ¿usualmente la gente usa un sistema de simultaneidad pesimista u optimista? ¿Qué impulsa la preferencia de usar una sobre otra y cuáles son algunas de las consideraciones de diseño a tener en cuenta?Preferencia de base de datos preferida/diseño de concurrencia cuando varios usuarios pueden editar los mismos datos

Actualmente me estoy inclinando por una comprobación de concurrencia optimista, ya que parece más indulgente, pero me preocupa la posibilidad de que se realicen múltiples cambios que podrían estar en contradicción entre sí.

Gracias!

Respuesta

3

Bloqueo optimista.
Pesimista es más difícil de implementar y dará problemas en un entorno web. ¿Qué acción liberará el bloqueo y cerrará el navegador? ¿Dejando la sesión a tiempo de espera? ¿Y si luego guardan sus cambios?

No especifica qué base de datos está utilizando. El servidor MS SQL tiene un tipo de datos de marca de tiempo. Sin embargo, no tiene nada que ver con el tiempo. Es un número que cambiará cada vez que se actualice la fila. No tiene que hacer nada para asegurarse de que se modifique, solo necesita verificarlo. Puede lograr resultados similares utilizando una fecha/hora modificada por última vez como lo sugiere @KM. Pero esto significa que debe recordar cambiar cada vez que actualice la fila. Si usa datetime, necesita usar un tipo de datos con la precisión suficiente para asegurarse de que no pueda terminar con el valor que no cambia cuando debería. Por ejemplo, alguien guarda una fila, luego alguien la lee y luego se guarda otra, pero no cambia la fecha/hora modificada. Usaría la marca de tiempo a menos que haya un requisito para seguir la fecha de la última modificación en los registros.

Para comprobarlo, puede hacer lo que @KM sugiere e incluirlo en la cláusula update statement where. O puede comenzar una transacción, verificar la marca de tiempo, si todo está bien hacer la actualización, luego confirmar la transacción, si no, devolver un error o código de falla.

La celebración de transacciones abiertas (como lo sugiere @le dorfier) ​​es similar al bloqueo pesimista, pero la cantidad de datos bloqueados puede ser más que una fila. La mayoría de los bloqueos RDBM en el nivel de página por defecto.También se encontrará con los mismos problemas que con el bloqueo pesimista.

Menciona en su pregunta que le preocupan las actualizaciones conflictivas. Eso es lo que el bloqueo evitará seguramente. Tanto la voluntad optimista como la pesimista, cuando se implementan adecuadamente, evitan exactamente eso.

+0

Me gusta la fecha del último cambio mejor que el tipo de datos de marca de tiempo porque contiene datos útiles. También tenemos un LastChgID para rastrear a la persona, ambas columnas son agradables de mostrar, donde una columna de tipo de datos de marca de tiempo no tiene sentido para mostrar. –

+0

Si este tipo de datos ya es un requisito, entonces no hay razón para no usarlo. He actualizado mi respuesta en consecuencia. – pipTheGeek

0

Supongo que está experimentando el problema de "actualización perdida".

Para contrarrestar esto como regla general utilizo el bloqueo pesimista cuando las posibilidades de una colisión son altas (o las transacciones son de corta duración) y el bloqueo optimista cuando las posibilidades de una colisión son bajas (o las transacciones son de larga duración, o sus reglas comerciales abarcan múltiples transacciones).

Realmente necesita ver lo que se aplica a su situación y hacer una llamada de juicio.

+0

Además, nunca colocaría bloqueos pesimistas en las ediciones de espera del usuario. –

+0

@DJ buen punto, me olvidé de mencionar eso. – Glen

+0

@Glen dijo que "una cosa a tener en cuenta aquí es que si se producen 2 actualizaciones dentro de la resolución de la columna Fecha tu lógica fallará. Es un caso marginal bastante raro, pero aún puede ocurrir". Sin embargo, uno obtendrá el bloqueo (recuerde que está en una transacción), el otro no y esperará y las fechas serán diferentes cuando tenga oportunidad de actualizar. –

1

he aquí una solución simple para muchas personas que trabajan en los mismos registros.

cuando se cargan los datos, obtener la fecha de última modificación, que utilizamos en nuestras mesas LastChgDate

cuando se guarda (actualización) los datos se suman "Y LastChgDate = previouslyLoadedLastChgDate" a la cláusula where. Si el recuento de filas = 0 en la actualización, emita un error donde "alguien más ya ha guardado esta información" y restituya todo; de lo contrario, se guardarán los datos.

Por lo general, hago la lógica anterior solo en tablas de encabezado y no en las tablas de detalles, ya que todas están en una transacción.

+0

Una cosa a tener en cuenta es que si se producen 2 actualizaciones dentro de la resolución de la columna Fecha, su lógica fallará. Es un caso muy raro, pero aún puede ocurrir. – Glen

+0

@Glen, uno obtendrá el candado (recuerde que está en una transacción), el otro no y esperará y las fechas serán diferentes cuando tenga oportunidad de actualizar. –

3

Acepto la primera respuesta anterior, tratamos de usar un bloqueo optimista cuando la probabilidad de colisiones es bastante baja. Esto se puede implementar fácilmente con una columna LastModifiedDate o incrementando una columna de Versión. Si no está seguro acerca de la frecuencia de las colisiones, registre las instancias en algún lugar para que pueda vigilarlas. Si sus registros están siempre en el modo "editar", tener los modos "ver" y "editar" separados podría ayudar a reducir las colisiones (suponiendo que vuelva a cargar los datos al ingresar al modo de edición).

Si las colisiones siguen siendo elevadas, el bloqueo pesimista es más difícil de implementar en aplicaciones web, pero definitivamente es posible. Hemos tenido un buen éxito con los registros de "arrendamiento" (bloqueo con un tiempo de espera) ... similar a esa advertencia de 2 minutos que obtienes al comprar boletos en TicketMaster. Cuando un usuario entra en modo de edición, colocamos un registro en la tabla de "bloqueo" con un tiempo de espera de N minutos. Otros usuarios verán un mensaje si intentan editar un registro con un bloqueo activo. También puede implementar un keep-alive para formularios largos renovando el contrato de arrendamiento en cualquier devolución de datos de la página, o incluso con un temporizador ajax. Tampoco hay ninguna razón por la que no pueda respaldar esto con un bloqueo optimista estándar mencionado anteriormente.

Muchas aplicaciones necesitarán una combinación de ambos enfoques.

Cuestiones relacionadas