10

siguiente declaración:abortado debido al conflicto actualizar

INSERT INTO dbo.Changes([Content], [Date], [UserId], [CompanyId]) 
    VALUES (@1, @2, @3, @4); 
SELECT @@identity; 

me da este error SQL 3960:

transacción de aislamiento de instantánea abortado debido a la actualización de los conflictos. Usted no puede usar el aislamiento de instantáneas para acceder a la tabla 'dbo.Companies' directamente o indirectamente en la base de datos 'myDatabase' para actualizar, eliminar o insertar la fila que ha sido modificada o eliminada por otra transacción. Vuelva a intentar la transacción o cambie el nivel de aislamiento para la declaración de actualización/eliminación .

Por lo que he entendido, desde el mensaje de error, no debería actualizar, eliminar o insertar a la mesa dbo.Companies durante el tiempo de otra conexión está modificando dbo.Companies.

Pero por qué se produce cuando estaba insertar una nueva fila a otra mesa dbo.Changes (que tiene la clave externa a dbo.Companies) y no estaba borrando la fila hace referencia en dbo.Companies, pero estaba actualizando fila de dbo.Companies y no primaria ¿llave? Esto debería funcionar bien, ¿no es así? (¿Es un error en SQL Server?)

ACTUALIZACIÓN:

Tablas se parece a lo siguiente:

dbo.Changes([Id] int PK, [Content] nvarchar, 
    [Date] datetime, [UserId] int, [CompanyId] int -> dbo.Companies.[Id]) 
dbo.Companies([Id] int PK, [Name] nvarchar) 

Segunda actualización está haciendo:

UPDATE dbo.Companies WHERE [Id] = @1 SET [Name] = @2; 

Respuesta

5

Parece SQL El servidor adquirirá los bloqueos de actualización en cualquier registro que tenga que leer aunque no lo modifique.

Más información sobre este microsoft.public.sqlserver.server thread:

Sin un índice de apoyo sobre CustomerContactPerson, la declaración

Borrar de la Persona de contacto donde id = @ID;

requerirá una "corriente" lectura de todas las filas de CustomerContactPerson para asegurar que no hay filas CustomerContactPerson que se refieren a la fila eliminada Persona de contacto. Con el índice, el DELETE puede determinar que no hay filas relacionadas en CustomerContactPerson sin leer las filas afectadas por la otra transacción.

Además, en una transacción de instantánea el patrón para la lectura de datos que se va a girar en torno y actualización es tomar un UPDLOCK cuando se lee. Esto asegura que está haciendo su actualización sobre la base de datos "actuales", no datos "consistentes" (instantánea), y que cuando emite el DML, los datos no se bloquearán, y usted ganó ' t involuntariamente sobrescribe otro cambio de la sesión .

La corrección para nosotros fue agregar índices a las claves externas

En su ejemplo, sospecho añadir un índice a Changes.CompanyId ayudará. No estoy seguro si esta es una solución real. ¿Puede el optimizador de SQL Server elegir no usar el índice?

+0

Gracias por las sugerencias, pero no parece ser de ayuda. –

+0

¿Ambas declaraciones (INSERTAR y ACTUALIZAR) se refieren al mismo Cliente? Si es así, no tenemos suerte hasta donde yo sé. –

+0

Sí, insertar está usando el ID de la empresa que se está actualizando actualmente. –

3

SQL Server puede ver una actualización de una tabla dependiente que PODRÍA modificar el comportamiento de la inserción ... me parece justo ya que SQL no puede adivinar de qué otra lógica podría depender o n [nombre] columna (disparadores etc.)

si sus aplicaciones implementan la lógica de reintento de bloqueo puede modificarlos para tratar el error no 3960 lo mismo que el error no 1205 y vuelva a intentar automáticamente ...

+0

Hace un buen punto ... excepto, todavía no entiendo por qué tener un índice no agrupado y no único en la columna de la clave externa de la tabla relacionada es suficiente para que esto no suceda, es decir, no es el caso que todavía podría modificar el comportamiento de la inserción, incluso con el índice? – Kram

+0

@Kram Supongo que el índice ayuda a la granularidad. El motor sabe que una tabla dependiente debe estar bloqueada, pero sin un índice puede intentar bloquear toda la tabla en lugar de una sola fila – jean

Cuestiones relacionadas