sql server - tabla - Edición de registros de la base de datos por múltiples usuarios
funciones definidas por el usuario sql server (8)
@ Mark Harrison: SQL Server no admite esa sintaxis ( SELECT ... FOR UPDATE
).
El equivalente de SQL Server es la sugerencia de la instrucción SELECT
UPDLOCK
.
Consulte los libros en línea de SQL Server para obtener más información.
He diseñado tablas de bases de datos (normalizadas, en un servidor MS SQL) y he creado una interfaz de usuario independiente para una aplicación que será utilizada por un puñado de usuarios para agregar y editar información. Añadiremos 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 comprometer la actualización sería el "ganador" y se podría perder información importante. Me vienen a la mente varias soluciones, pero no estoy seguro de si voy a crear un mayor dolor de cabeza.
- No haga nada y espere que dos usuarios nunca editen el mismo registro al mismo tiempo. - Puede que nunca haya pasado, pero ¿y si sucede?
- 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, muestra la actualización del usuario y de la confirmación : se requerirán dos copias de datos para almacenar.
- 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.
- Cree una tabla de edición que se registre cuando los usuarios comiencen a editar un registro que será verificado y evitará que otros usuarios editen el mismo registro. - requeriría una cuidadosa reflexión del flujo del programa para evitar bloqueos y que los registros se bloqueen si un usuario se bloquea fuera del programa.
¿Hay alguna solución mejor o debería elegir una de estas?
La base de datos hará esto por ti. 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.
Otra opción es probar que los valores en el registro que cambias son los mismos que cuando comenzaste:
SELECT
customer_nm,
customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id
(muestre 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 agregar una nueva columna a su tabla (y mantenerla actualizada), pero sí tiene que crear más sentencias SQL detalladas y pasar campos "nuevos" y "antiguos" al procedimiento almacenado.
También tiene la ventaja de que no bloquea los registros, porque todos sabemos que los registros terminarán bloqueados cuando no deberían ...
SELECT FOR UPDATE y los equivalentes son buenos siempre que mantenga el bloqueo durante un tiempo microscópico, pero para una cantidad macroscópica (por ejemplo, el usuario tiene los datos cargados y no ha pulsado ''guardar'', debe utilizar la concurrencia optimista como se indicó anteriormente. Siempre pienso que tiene un nombre equivocado: es más pesimista que el "último escritor gana", que generalmente es la única alternativa considerada).
Un enfoque clásico es el siguiente:
- agregue un campo booleano, "bloqueado" a cada tabla.
- establezca esto como falso por defecto.
cuando un usuario comienza a editar, usted hace esto:
- bloquear la fila (o toda la mesa si no puedes bloquear la fila)
- revisa la bandera en la fila que deseas editar
- si la bandera es verdadera, entonces
- informar al usuario que no pueden editar esa fila en este momento
- más
- establecer la bandera en verdadero
suelta el candado
al guardar el registro, establezca la bandera en falso
Conmigo, la mejor manera que tengo una columna lastupdate (tipo de datos de marca de tiempo). cuando seleccione y actualice simplemente compare este valor, otro avance de esta solución es que puede usar esta columna para rastrear el tiempo en que los datos han cambiado. Creo que no es bueno si solo creas una columna como isLock para verificar la actualización.
Si espera colisiones infrecuentes, 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
-primero crear archivado (hora de actualización) para almacenar el último registro de actualización -cuando cualquier usuario seleccione grabar guardar seleccionar hora, comparar entre seleccionar hora y actualizar el campo de tiempo si (hora de actualización)> (seleccionar hora) significa que otro usuario actualizará este registro después de seleccionar grabar