Pregunta

Diseñé tablas de bases de datos (normalizadas, en un servidor MS SQL) y creé una interfaz de Windows independiente para una aplicación que será utilizada por un puñado de usuarios para agregar y editar información.Agregaremos una interfaz web para permitir la búsqueda en nuestra área de producción en una fecha posterior.

Me preocupa que si dos usuarios comienzan a editar el mismo registro, el último en confirmar la actualización será el "ganador" y se puede perder información importante.Se me ocurren varias soluciones, pero no estoy seguro de si voy a crear un dolor de cabeza mayor.

  1. No haga nada y espere que dos usuarios nunca editen el mismo registro al mismo tiempo. - Puede que nunca suceda, pero ¿y si sucede?
  2. La rutina de edición podría almacenar una copia de los datos originales, así como las actualizaciones, y luego comparar cuando el usuario haya terminado de editar.Si difieren, muestre el usuario y confirme la actualización. - Requeriría almacenar dos copias de los datos.
  3. Agregue la última columna DATETIME actualizada y verifique que coincida cuando actualicemos; de lo contrario, muestre las diferencias. - requiere una nueva columna en cada una de las tablas relevantes.
  4. Cree una tabla de edición que registre cuándo los usuarios comienzan a editar un registro que se verificará y evitará que otros usuarios editen el mismo registro. - Requeriría pensar cuidadosamente en el flujo del programa para evitar interbloqueos y registros bloqueados si un usuario sale del programa.

¿Hay alguna solución mejor o debería optar por una de estas?

¿Fue útil?

Solución

Si espera colisiones poco frecuentes, Simultaneidad optimista es probablemente tu mejor opción.

Scott Mitchell escribió un tutorial completo sobre cómo implementar ese patrón:
Implementación de concurrencia optimista

Otros consejos

Un enfoque clásico es el siguiente:

  • agregue un campo booleano, "bloqueado" a cada tabla.
  • establezca esto en falso de forma predeterminada.
  • cuando un usuario comienza a editar, haces esto:

    • bloquear la fila (o toda la tabla si no puede bloquear la fila)
    • marque la bandera en la fila que desea editar
    • si la bandera es verdadera entonces
      • informar al usuario que no puede editar esa fila en este momento
    • demás
      • establecer la bandera en verdadero
    • suelta el bloqueo

    • al guardar el registro, vuelva a establecer el indicador en falso

SELECCIONAR PARA ACTUALIZAR y equivalentes son buenos siempre que mantenga presionado el candado durante un período de tiempo microscópico, pero durante un período macroscópico (p. ej.el usuario tiene los datos cargados y no ha presionado "guardar", debe usar la simultaneidad optimista como se indicó anteriormente.(Lo cual siempre pienso que está mal llamado: es más pesimista que "el último escritor gana", que suele ser la única otra alternativa considerada).

@Mark Harrison:SQL Server no admite esa sintaxis (SELECT ... FOR UPDATE).

El equivalente de SQL Server es el SELECT sugerencia de declaración UPDLOCK.

Ver Libros en línea de SQL Server para más información.

-Rested First Create Arched (Tiempo de actualización) para almacenar el último registro de actualización -Cuenta de cualquier usuario El registro de selección Guardar tiempo de selección, compare entre el tiempo de selección y el campo de tiempo de actualización if (tiempo de actualización)> (tiempo de selección) que significa otro usuario actualizar este registro después de seleccionar registro

Otra opción es probar que los valores en el registro que está cambiando siguen siendo los mismos que cuando comenzó:

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(muestra el campo customer_nm y el usuario lo cambia)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

No es necesario que agregue una nueva columna a su tabla (y la mantenga actualizada), pero sí debe crear declaraciones SQL más detalladas y pasar nuevo y viejo campos al procedimiento almacenado.

También tiene la ventaja de que no se bloquean los registros, porque todos sabemos que los registros terminarán bloqueados cuando no deberían estarlo...

La base de datos hará esto por usted.Mira "seleccionar...for update", que está diseñado sólo para este tipo de cosas.Le dará un bloqueo de escritura en las filas seleccionadas, que luego podrá confirmar o revertir.

Para mí, la mejor manera es tener una última actualización de columna (tipo de datos de marca de tiempo).Cuando se seleccione y actualice, simplemente compare este valor, otro avance de esta solución es que puede usar esta columna para rastrear el tiempo que los datos tienen cambios.Creo que no es bueno si simplemente creas una columna como isLock para verificar la actualización.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top