Yii2 уникальный валидатор не работает, когда вставить так быстро

Я использую модель ActiveRecord для сохранения данных.

Unique Validator работает очень идеально. Но когда я так быстро вставляю данные, они перестают работать идеально. В какой-то запрос я получаю сообщение об ошибке, которое не может поймать Yii.

Нарушение целостности — yii \ db \ IntegrityException
SQLSTATE [23000]: нарушение ограничения целостности: 1062 Повторяющаяся запись
‘***’ …

Есть ли у нас какое-либо решение для решения этой проблемы без добавления другого сервиса?

Спасибо !

1

Решение

Подводя итоги в комментариях …

Скорее всего, вам нужно вручную заблокировать таблицу перед проверкой и снять блокировку после нее. Yii2 обеспечивает оптимистичные замки механизм, но это не подходит для вашего случая. Оптимистичные замки поддерживаются только внутри методов update и delete:

Оптимистическая блокировка поддерживается только при обновлении или удалении
существующая строка данных с использованием yii \ db \ ActiveRecord :: update () или
yii \ db \ ActiveRecord :: delete () соответственно.

Более того, что делает оптимистическую блокировку, так это просто вызывает исключение, когда обновление завершается неудачно из-за конфликта (без фактической блокировки таблицы)

Решение будет зависеть от вашего движка БД. Yii2 обеспечивает мьютекс механизм для ручной блокировки. Из коробки Yii2 поддерживал Mysql и Postgres. См. Описание компонентов на следующих страницах руководства Yii2:

Итак, после того, как вы настроили свой мьютекс в конфиге (пример для pgsql из официального руководства):

[
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'pgsql:host=127.0.0.1;dbname=demo',
]
'mutex' => [
'class' => 'yii\mutex\PgsqlMutex',
],
],
]

вам нужно сделать что-то подобное

\Yii::$app->mutex->acquireLock($lockingObject);

// validate uniqueness and save

\Yii::$app->mutex->releaseLock($lockingObject);

Или же, наверняка вы можете сделать это вручную, используя синтаксис SQL вашей СУБД.

MySQL:

SELECT GET_LOCK('tablename',10);
SELECT RELEASE_LOCK('tablename');

Pqsql:

LOCK TABLE tablename IN SHARE ROW EXCLUSIVE MODE;

Имейте в виду, что блокировка Pgsql работает только внутри транзакции.

1

Другие решения

Мое решение этой проблемы:

  • Unique Validator не работает в этом случае
  • Я использую INSERT IGNORE игнорировать новую запись, если существует. Это работает очень быстро.
0

По вопросам рекламы [email protected]