MySQL: ВСТАВИТЬ НА ОБНОВЛЕНИЕ ДУБЛИКАЦИИ КЛЮЧА: затронутые строки == 3?

В документации MySQL указано, что при использовании INSERT ... ON DUPLICATE KEY UPDATE значение затронутых строк будет равно 1 при вставке записи и 2 при обновлении существующей записи.

Мы получаем значение затронутых строк, равное 3, когда запись обновляется, хотя я вижу это только тогда, когда обновления выполняются через вызовы MySQL с использованием Connector-J из Java; когда я вызываю хранимую процедуру из MySQL Workbench, я получаю ожидаемый результат обновления 2 строк.

Кто-нибудь знает, что это может означать? Возможно, это аномалия Connector-J? Я был бы склонен просто работать с ним, но без разумного объяснения у меня остались опасения за целостность моих данных (что, в конце концов, является одной из причин для проверки значения затронутых строк).

Версия сервера MySQL: 5.1.57; Версия Connector-J: 5.1.7 (Java 1.6)

Дополнительная информация: это изменяемая таблица:

CREATE TABLE `UserContactProperty` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `UserContactId` int(11) NOT NULL,
  `Property` varchar(45) NOT NULL,
  `Value` tinytext,
  `Date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `Contact-Property` (`UserContactId`,`Property`),
  KEY `FK_UserContact` (`UserContactId`),
  CONSTRAINT `FK_UserContact` FOREIGN KEY (`UserContactId`) REFERENCES `UserContact` (`id`) ON   DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=28685 DEFAULT CHARSET=latin1

Хранимая процедура, выполняющая вставку/обновление, выглядит следующим образом:

CREATE PROCEDURE `setUserContactProperty`(
    UID VARCHAR(50),
    CID INT,
    Prop VARCHAR(45),
    Val TINYTEXT
)
BEGIN
    INSERT INTO UserContactProperty ( UserContactId, Property, Value )
        VALUES ( CID, Prop, Val )
        ON DUPLICATE KEY UPDATE Value = Val, Date = CURRENT_TIMESTAMP;
END

person Ben Schreiber    schedule 20.07.2012    source источник
comment
Вы можете включить общее ведение журнала или добавить profileSQL=true в строку подключения JDBC, чтобы точно видеть, что отправляется на сервер.   -  person Joshua Martell    schedule 20.07.2012


Ответы (1)


Это похоже на ошибку. пожалуйста, проверьте следующую ссылку:

http://bugs.mysql.com/bug.php?id=46675

Как сообщается там, ошибка связана с другой ошибкой, из-за которой сгенерированный список ключей неверен, и счетчик тоже неверен. (вторая ошибка возникла отсюда http://slava-technical.blogspot.co.il/2011/05/mysql-on-duplicate-key-update-breaks.html)

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

person Community    schedule 20.07.2012
comment
не забудьте обернуть эти запросы в транзакцию, чтобы не пропустить параллельную вставку после того, как вы сначала проверите существование. При этом убедитесь, что ваш механизм хранения поддерживает транзакции (скажем, MyISAM не поддерживает). В качестве альтернативы, обеспечьте блокировку другими способами (например, разрешив обработку только 1 запроса за раз для сервера). - person spacediver; 20.07.2012
comment
Спасибо за ссылку на отчет об ошибке - очень информативно! В качестве обходного пути, я думаю, я воспользуюсь своим первым инстинктом: рассматривайте 3 как допустимое возвращаемое значение и синоним для 2. Нигде в документах об ошибках не предполагалось, что значения, отличные от 3, были возможны (за исключением более старых версий сервера). , которые меня не касаются). - person Ben Schreiber; 20.07.2012