Recientemente me han encargado la depuración de un problema extraño dentro de una aplicación de comercio electrónico. Después de una actualización de la aplicación, el sitio comenzó a colgar de vez en cuando y me enviaron a depuración. Después de verificar el registro de eventos, encontré que el servidor SQL escribió ~ 200 000 eventos en un par de minutos con el mensaje que decía que una restricción había fallado. Después de mucha depuración y algunos rastreos encontré al culpable. He quitado algo de código innecesario y limpié un poco, pero básicamente esto es élWhile-cláusula en T-SQL que se repite siempre
WHILE EXISTS (SELECT * FROM ShoppingCartItem WHERE ShoppingCartItem.PurchID = @PurchID)
BEGIN
SELECT TOP 1
@TmpGFSID = ShoppingCartItem.GFSID,
@TmpQuantity = ShoppingCartItem.Quantity,
@TmpShoppingCartItemID = ShoppingCartItem.ShoppingCartItemID,
FROM
ShoppingCartItem INNER JOIN GoodsForSale on ShoppingCartItem.GFSID = GoodsForSale.GFSID
WHERE ShoppingCartItem.PurchID = @PurchID
EXEC @ErrorCode = spGoodsForSale_ReverseReservations @TmpGFSID, @TmpQuantity
IF @ErrorCode <> 0
BEGIN
Goto Cleanup
END
DELETE FROM ShoppingCartItem WHERE ShoppingCartItem.ShoppingCartItemID = @TmpShoppingCartItemID
-- @@ROWCOUNT is 1 after this
END
Datos:
- sólo hay uno o dos registros que coincide con el de primera cláusula select
- RowCount de la instrucción DELETE indica que se ha eliminado
- el bucle WHILE cláusula siempre
El procedimiento se ha reescrito para seleccionar las filas que se deben eliminar en una tabla temporal en memoria para que se solucione el problema inmediato, pero esto realmente despertó mi curiosidad.
¿Por qué gira para siempre?
Aclaración: El borrado no falla (@@ recuento de filas es 1 después de la stmt borrado cuando depurando) Aclaración 2: No debería importar si es o no la parte superior SELECT ... cláusula se ordena por cualquier campo específico ya que el registro con la identificación devuelta se eliminará, por lo que en el siguiente ciclo debería obtener otro registro.
Actualización: Después de verificar los registros de subversión, encontré la confirmación de culpa que hizo que este procedimiento almacenado se volviera loco. La única diferencia real que puedo encontrar es que anteriormente no había unión en la instrucción SELECT TOP 1, es decir, sin esa unión funcionó sin ninguna declaración de transacción que rodeara la eliminación. Parece ser la introducción de la combinación que hizo que el servidor SQL sea más exigente.
actualización aclaración: brien señaló que no hay necesidad de la unión, sino que se hace realmente utilizar algunos campos de la tabla GoodsForSale pero yo les he quitado para mantener el código simplemente para que podamos concentrarnos en el problema mano
¿Qué restricción falló? ¿Estaba en ShoppingCartItem o GoodsForSale? – brien
Vea mi respuesta, ¿esta pregunta aún está abierta? –