Я использую модель ActiveRecord для сохранения данных.
Unique Validator
работает очень идеально. Но когда я так быстро вставляю данные, они перестают работать идеально. В какой-то запрос я получаю сообщение об ошибке, которое не может поймать Yii.
Нарушение целостности — yii \ db \ IntegrityException
SQLSTATE [23000]: нарушение ограничения целостности: 1062 Повторяющаяся запись
‘***’ …
Есть ли у нас какое-либо решение для решения этой проблемы без добавления другого сервиса?
Спасибо !
Подводя итоги в комментариях …
Скорее всего, вам нужно вручную заблокировать таблицу перед проверкой и снять блокировку после нее. 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 вашей СУБД.
SELECT GET_LOCK('tablename',10);
SELECT RELEASE_LOCK('tablename');
LOCK TABLE tablename IN SHARE ROW EXCLUSIVE MODE;
Имейте в виду, что блокировка Pgsql работает только внутри транзакции.
Мое решение этой проблемы:
Unique Validator
не работает в этом случае INSERT IGNORE
игнорировать новую запись, если существует. Это работает очень быстро.