mysql sql-update duplicates

MySQL 5.5.24-Entrada duplicada en ACTUALIZACIÓN, cuando no hay un duplicado real



sql-update duplicates (1)

Tengo que actualizar una tabla con la siguiente estructura:

CREATE TABLE `eav_entity_attribute` ( `entity_attribute_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT ''Entity Attribute Id'', `entity_type_id` smallint(5) unsigned NOT NULL DEFAULT ''0'' COMMENT ''Entity Type Id'', `attribute_set_id` smallint(5) unsigned NOT NULL DEFAULT ''0'' COMMENT ''Attribute Set Id'', `attribute_group_id` smallint(5) unsigned NOT NULL DEFAULT ''0'' COMMENT ''Attribute Group Id'', `attribute_id` smallint(5) unsigned NOT NULL DEFAULT ''0'' COMMENT ''Attribute Id'', `sort_order` smallint(6) NOT NULL DEFAULT ''0'' COMMENT ''Sort Order'', PRIMARY KEY (`entity_attribute_id`), UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_ATTRIBUTE_ID` (`attribute_set_id`,`attribute_id`), UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID` (`attribute_group_id`,`attribute_id`), KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_SORT_ORDER` (`attribute_set_id`,`sort_order`), KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_ID` (`attribute_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=''Eav Entity Attributes''

La tabla de arriba contiene una sola fila:

INSERT INTO `eav_entity_attribute` (`entity_attribute_id`, `entity_type_id`, `attribute_set_id`, `attribute_group_id`, `attribute_id`, `sort_order`) VALUES (32758, 4, 224, 3423, 5171, 12)

Estoy ejecutando un procedimiento de importación automática, que leerá una fuente de datos externa y la escribiré en esta tabla.

Esta importación se ejecuta varias veces y, por lo tanto, a veces se importan los mismos datos varias veces. En tal caso, el procedimiento simplemente sobrescribe los datos antiguos con los nuevos, incluso cuando los nuevos son idénticos a los antiguos. La condición en la que existen los mismos datos se maneja con una cláusula ON DUPLICATE KEY UPDATE. Esto funciona casi perfectamente, excepto en esta tabla específica.

En esta tabla, cuando el procedimiento intenta una ACTUALIZACIÓN, recibo un mensaje de "Duplicar clave", que no puedo explicar. Depuré el código, y esta es la consulta que falla (extraída de la LLAVE DE DUPLICACIÓN INSERT..ON):

UPDATE eav_entity_attribute SET `attribute_group_id` = 3423 ,`attribute_id` = 5171 ,`attribute_set_id` = 223 ,`entity_type_id` = 4 ,`sort_order` = 320 WHERE (`attribute_group_id` = 3423) AND (`attribute_id` = 5171)

El error es el siguiente:

Error Code: 1062. Duplicate entry ''3423-5171'' for key ''UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID''

Sé que el par 3423-5171 ya existe, pero la ACTUALIZACIÓN reemplazará estos valores por sí mismos, no creará una nueva entrada. Estoy bastante confundido acerca de la causa de este problema, cualquier sugerencia sería muy bienvenida. Gracias.

Actualización - Nuevo hallazgo

Conseguí una especie de "inspiración" e hice un experimento. Eliminé la restricción Única relacionada con ( attribute_set_id , attribute_id ) (nota, esta no es la que está en el error) y ejecuté la consulta INSERT..ON DUPLICATE. Funcionó perfectamente.

La mía es una conjetura, pero esto es lo que pienso: los datos que intento escribir en la tabla chocan con dos restricciones:

  • ÚNICO ( attribute_set_id , attribute_id )
  • ÚNICO ( attribute_group_id , attribute_id )

El INSERT falla, probablemente debido al error de duplicación generado por la primera restricción. Esto activa la ACTUALIZACIÓN, que utiliza la primera restricción como la cláusula WHERE implícita. Mi especulación es que, en tal caso, la primera restricción se ignora de alguna manera, pero la ACTUALIZACIÓN se dispara sobre la segunda, que no se involucró antes.

Esto aún no me parece una razón válida para una ACTUALIZACIÓN que reemplace algo consigo mismo para generar un error de entrada duplicado, pero puede arrojar algo de luz sobre la lógica detrás de esto.

Segunda actualización

Descubrí que la tabla con la que estaba probando en realidad contiene muchas filas (olvidé desactivar la vista filtrada) como resultado de la importación exitosa de otros datos. Sin embargo, el "candidato duplicado" sigue siendo único en el conjunto.

Confirmo lo que se publicó en los comentarios, cuando la tabla solo contiene esas filas, el INSERT..ON DUPLICATE funciona, así como la ACTUALIZACIÓN sola. Ahora me pregunto por qué la tabla se desordena cuando hay más datos en ella, ya que todavía estamos hablando de una única fila única que se actualiza con los mismos datos.

Tercera actualización - Encontró la causa raíz

Finalmente descubrí la razón por la cual falla la ACTUALIZACIÓN, ahora tengo que averiguar cómo me pongo en tal condición.

La pista fue mi conjetura en la primera actualización. Simplemente, tengo dos filas muy similares (tenga en cuenta que estoy usando valores diferentes cuando comencé desde una base de datos limpia).

row,entity_attribute_id,entity_type_id,attribute_set_id,attribute_group_id,attribute_id,sort_order 1,16919, 4, 120, 1746, 80, 1 2,16649, 4, 119, 1744, 80, 210

Esto es lo que sucede:

  • El INSERT intenta insertar una fila con los siguientes valores: 120, 4, 1744, 80, 54 .
  • Esto dispara la "clave duplicada", ya que los valores 120, 80 son un duplicado para los campos attribute_set_id, attribute_id (fila 1).
  • MySQL luego intenta la ACTUALIZACIÓN, que se convierte en lo siguiente:

    ACTUALIZAR la tabla entity_type_id = 4, attribute_group_id = 1744, sort_order = 54 WHERE ( attribute_set_id = 120) AND ( attribute_id = 80)

  • Esta vez, la ACTUALIZACIÓN falla porque los valores 1744,80 violan la restricción en el par attribute_group_id, attribute_id , que se encuentra en la fila 2.

En resumen

  • El INSERT falla porque la fila 1 tiene los mismos valores para la clave attribute_set_id, attribute_id .
  • La ACTUALIZACIÓN falla porque la fila 2 tiene los mismos valores para la clave attribute_group_id, attribute_id .

Solución

Tendré que revisar todo el procedimiento de importación, ya que, en teoría, ninguno de estos duplicados debería surgir. MySQL está haciendo su trabajo bien, es la base de datos que es complicada.

Gracias por todas las sugerencias.


Intente no actualizar los valores clave dentro de la cláusula UPDATE de INSERT ... ON DUPLICATE KEY UPDATE . Es extraño pedirle a MySQL que cambie los valores clave si ya existe un registro con estos valores clave, por lo que el comportamiento inesperado de MySQL no es sorprendente.