MySQL 5.5.24 - Дублирующая запись в UPDATE, когда нет реального дубликата

Мне нужно обновить таблицу со следующей структурой:

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'

Над таблицей содержит одну строку:

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)

У меня запущена автоматическая процедура импорта, которая будет читать внешний источник данных и записывать в эту таблицу.

Этот импорт выполняется несколько раз, и поэтому иногда одни и те же данные импортируются несколько раз. В этом случае процедура просто перезаписывает старые данные с новой, даже если новая идентична старой. Условие, когда одни и те же данные существуют, обрабатывается с предложением ON DUPLICATE KEY UPDATE. Это работает почти отлично, за исключением этой конкретной таблицы.

В этой таблице, когда процедура пытается выполнить UPDATE, я получаю сообщение "Дубликат", которое я не могу объяснить. Я отлаживал код, и это запрос, который терпит неудачу (извлечен из INSERT..ON DUPLICATE KEY):

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)

Ошибка следующая:

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

Я знаю, что пара 3423-5171 уже существует, но UPDATE заменит эти значения самим собой, а не создаст новую запись. Я очень смущен причиной этой проблемы, любое предложение было бы очень желанным. Спасибо.

Обновление - новое обнаружение

У меня появилось какое-то "вдохновение", и я сделал эксперимент. Я удалил ограничение Unique, в которое включено (attribute_set_id, attribute_id) (обратите внимание, что это не тот, который был в ошибке), и я запустил запрос INSERT..ON DUPLICATE. Он отлично работал.

Мина - это гипотеза, но это то, что я думаю: данные, которые я пытаюсь записать в таблицу, сталкиваются с двумя ограничениями:

  • UNIQUE (attribute_set_id, attribute_id)
  • UNIQUE (attribute_group_id, attribute_id)

Ошибка INSERT, предположительно из-за ошибки дублирования, вызванной ограничением first. Это вызывает UPDATE, который использует первое ограничение как неявное предложение WHERE. Мое предположение заключается в том, что в таком случае первое ограничение каким-то образом игнорируется, но UPDATE отключается во втором, что раньше не принималось.

Мне все еще не кажется, что это истинная причина для UPDATE, которая заменяет что-то сама собой, чтобы поднять дублируемую ошибку входа, но она может пролить свет на логику, лежащую за ней.

Второе обновление

Я узнал, что таблица, которую я тестировал, фактически содержит много строк (я забыл отключить отфильтрованное представление) в результате успешного импорта других данных. Однако "дублирующий кандидат" по-прежнему уникален в наборе.

Я подтверждаю, что опубликовано в комментариях, когда таблица содержит только эти строки, работает INSERT..ON DUPLICATE, а также только UPDATE. Теперь мне интересно, почему таблица перепуталась, когда в ней больше данных, поскольку мы все еще говорим о том, что одна уникальная строка обновляется с теми же данными.

Третье обновление - найдена коренная причина

Наконец-то я выяснил причину неудачи UPDATE, теперь я должен выяснить, как мне попасть в такое состояние.

Ключ был моей гипотезой в первом обновлении. Просто у меня есть две очень похожие строки (обратите внимание, что я использую разные значения, когда я начал с чистой базы данных).

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

Вот что происходит:

  • INSERT пытается вставить строку со следующими значениями: 120, 4, 1744, 80, 54.
  • Это вызывает "дубликат ключа", так как значения 120, 80 являются дубликатами для полей attribute_set_id, attribute_id (строка 1).
  • Затем MySQL запускает UPDATE, который выглядит следующим образом:

    Таблица UPDATE entity_type_id= 4 , attribute_group_id= 1744 , sort_order= 54 ГДЕ (attribute_set_id= 120) И (attribute_id= 80)

  • На этот раз UPDATE терпит неудачу, потому что значения 1744,80 нарушают ограничение на пару attribute_group_id, attribute_id, найденную в строке 2.

В заключение

  • INSERT терпит неудачу, потому что строка 1 имеет те же значения для ключа attribute_set_id, attribute_id.
  • Ошибка UPDATE, поскольку строка 2 имеет те же значения для ключа attribute_group_id, attribute_id.

Решение

Мне нужно будет просмотреть всю процедуру импорта, поскольку, теоретически, ни один из таких дубликатов не возникнет. MySQL выполняет свою работу отлично, это сложная база данных.

Спасибо за все предложения.

Ответы

Ответ 1

Попробуйте не обновлять значения ключа в UPDATE в разделе INSERT ... ON DUPLICATE KEY UPDATE. Странно попросить MySQL изменить ключевые значения, если запись с этими ключевыми значениями уже существует, поэтому неожиданное поведение MySQL не удивительно.