Edición de registros de base de datos por múltiples usuarios


He diseñado tablas de base de datos (normalizadas, en un servidor MS SQL) y creado un front-end 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, entonces el último en confirmar la actualización sería el 'ganador' y podría perderse información importante. Una serie de soluciones llegan a la mente, pero no estoy seguro de si voy a crear un dolor de cabeza más grande.

  1. No hacer nada y esperar que dos usuarios nunca van a estar editando el mismo registro al mismo tiempo. - Nunca podría suceder, pero ¿qué pasa si lo hace?
  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 show user y comfirm update - Requerirían dos copias de los datos para ser almacenados.
  3. Añadir el último actualizado DATETIME columna y comprobar que coincide cuando actualizamos, si no entonces mostrar diferencias. - requiere una nueva columna en cada una de las tablas pertinentes.
  4. Cree una tabla de edición que registre cuando los usuarios comiencen a editar un registro que se verificará y evite que otros usuarios editen el mismo registro. - requeriría pensar cuidadosamente en el flujo del programa para evitar que los bloqueos y los registros se bloqueen si un usuario se bloquea del programa.

¿Hay algo mejor soluciones o debería ir por una de estas?

Author: ConcernedOfTunbridgeWells, 2008-08-04

8 answers

Si espera colisiones poco frecuentes, La Concurrencia optimista es probablemente su mejor opción.

Scott Mitchell escribió un tutorial completo sobre la implementación de ese patrón:
Implementando la Concurrencia optimista

 13
Author: Dave Ward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-28 04:20:13

Un enfoque clásico es el siguiente:

  • agregue un campo booleano , "bloqueado" a cada tabla.
  • establezca esto en false de forma predeterminada.
  • Cuando un usuario comienza a editar, usted hace esto:

    • bloquear la fila (o toda la tabla si no se 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
    • else
      • establecer la bandera a verdadero
    • Suelte el bloqueo

    • Al guardar el registro, vuelva a poner la bandera en false

 2
Author: AJ.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 08:53:19

SELECCIONAR PARA ACTUALIZACIÓN y equivalentes son buenos siempre que mantenga el bloqueo durante una cantidad microscópica de tiempo, pero para una cantidad macroscópica (por ejemplo, el usuario tiene los datos cargados y no ha presionado 'guardar' debe usar concurrencia optimista como se mencionó anteriormente. (Que siempre creo que está mal llamado-es más pesimista que 'el último escritor gana', que suele ser la única otra alternativa considerada.)

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 05:39:22

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

El equivalente de SQL Server es la instrucción SELECT hint UPDLOCK.

Ver SQL Server Books Online para más información.

 1
Author: karlgrz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-05 05:56:44

- primero crear archivado (tiempo de actualización) para almacenar el último registro de actualización - cuando cualquier usuario seleccione grabar guardar seleccionar tiempo, comparar entre select time y update time campo si (update time) > (select time) eso significa que otro usuario actualiza este registro después de select record

 1
Author: mohamed elbagory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-14 11:23:05

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 tiene que añadir una nueva columna a su tabla (y mantenerla actualizada), pero sí tiene que crear instrucciones SQL más detalladas y pasar nuevos y antiguos campos al procedimiento almacenado.

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

 1
Author: Guy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-08 10:56:35

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

 0
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-04 02:30:09

Conmigo, la mejor manera que tengo una columna lastupdate (timetamp datatype). cuando seleccione y actualice solo compare este valor otro avance de esta solución es que puede usar esta columna para rastrear los datos de tiempo que tienen cambio. Creo que no es bueno si usted acaba de crear un colum como isLock para comprobar la actualización.

 0
Author: Linh danh thue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-24 07:14:00