Вставка MySQL выполнена успешно и возвращает идентификатор, но иногда не сохраняет данные при параллелизме

#mysql #concurrency #yii

#mysql #параллелизм #yii

Вопрос:

Я страдаю от одной странной проблемы. Я использую MySQL Enterprise Server ВЕРСИИ 8.

У меня есть один API, который выполняет следующие инструкции в базе данных Mysql :

 START TRANSACTION;
Many select statements;
INSERT INTO ... VALUES(...);
COMMIT;
Many select statements;
 

Это делает вставку в одну таблицу и извлекает идентификатор вновь созданной записи в таблице.
Это работает отлично, когда этот API вызывается при низкой нагрузке на сервер.

Но когда нагрузка на сервер увеличивается, она выполняется хорошо, а также возвращает вновь созданный идентификатор записи, но не сохраняет запись в базе данных.

В настоящее время, если я вызываю этот API 25 раз из интерфейса одновременно, то эта проблема возникает от 1 до 2 раз. т. Е. Я могу видеть все запросы и транзакции в журналах, и все они дают идентификатор записи, но 1-2 записи не сохраняются в базе данных.

Кто-нибудь может мне помочь в этом, если есть идеи?

Ответ №1:

Когда я имею дело с высоким уровнем параллелизма, я использую оператор ОБНОВЛЕНИЯ ДУБЛИРУЮЩЕГОСЯ КЛЮЧА. Это может решить вашу проблему.

https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

Но данные не вставляются в базу данных, но сервер не сообщил об ошибке, почему

Комментарии:

1. Нет, я не могу использовать это, так как мне не нужно обновлять, если ключ существует. В настоящее время, если я вызываю API, то все успешные и те предоставляют идентификаторы только последовательно, а не дублируют, поскольку это идентификатор первичного ключа с автоматическим увеличением.

2. Нет, эта операция просто следует принципу идемпотентности. Вы должны судить по коду if isExist() toUpdate() else toInsert() при одновременном использовании, нет гарантии, что isExist() метод получит правильный результат, поэтому ON DUPLICATE KEY UPDATE используется. Обратите внимание, что ON DUPLICATE KEY UPDATE используется только в toInsert() , не требуется в toUpdate() , и это также не инструкция update . Это гарантирует только то, что при вставке есть только одна запись для одного и того же primary key .