2016-07-21 3 views
1

Я использую модель ActiveRecord для сохранения данных.Yii2 Уникальный валидатор не работает при быстром вставке

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

Integrity нарушение ограничения - юй \ дб \ IntegrityException SQLSTATE [23000]: Integrity нарушение ограничения: 1062 Дублированный запись '***' ...

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

Спасибо!

+0

Что значит «вставить так быстро» ?? Уникальный валидатор работает на стороне сервера, как это влияет на скорость ввода данных на стороне клиента! –

+0

@ck_arjun eg: У меня есть список подарков на сайте, пользователь может нажать кнопку получения, чтобы получить подарок. Каждый подарок может быть получен только одним пользователем. Проблема заключается в том, что сотни людей нажимают кнопку получения. –

+1

yii может занять время после проверки и перед сохранением и его возможным, как в вашем случае, с тем же значением, которое будет сохранено в db. Я не знаю, есть ли у yii какие-либо способы обхода. Уловит ли исключение решение вашей проблемы? –

ответ

1

Подытоживая в комментариях ...

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

Оптимистическая блокировка поддерживается только при обновлении или удалении существующей строки данных, используя юй \ DB \ ActiveRecord :: Update() или юй \ 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 замок работает только внутри транзакции.

+0

Спасибо Максим , Locking - хорошее решение, но я думаю, что блокировка на уровне строк лучше –

+0

@ NgôVănThao да, уровень на ряду лучше. Обновите этот ответ, когда будете реализовывать свое решение. Поместите здесь рабочий пример. Это может помочь кому-то еще – oakymax

0

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

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