mitaichik
@mitaichik

Как блокировать строку в БД при чтении?

Всем привет!

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

Проблемы возникают когда одновременно регаются несколько юзеров - возможна ситуация когда они одновременно получат один и тот же промокод, а в сам промокод запишеться последний юзер.

Как такого избежать?

Я вижу несколько решений, но все какие-то неказистые: юзать redis с его incr который содержит id следующего свободного промокода (они автоинкременты), можно сделать очередь с одним воркером на получение свободного промокода, можно вообще сделать отдельный fpm пул с единственным php-fpm процессом (это конечно садомазо) или ограничить очередь на запрос регистрации юзера в nginx.

Но наверняка же есть какой-то простой способ?

Заранее спасибо.
  • Вопрос задан
  • 302 просмотра
Решения вопроса 2
Sanasol
@Sanasol
нельзя просто так взять и загуглить ошибку
зачем их заранее генерировать вообще?

Любо мало мальски рандомный генератор сделать при регистрации и промокод готов.

Если отбросить варианты из разряда promo_code_{user_id}

Ну или выбирать select for update чтобы лочилась строка
https://dev.mysql.com/doc/refman/5.7/en/innodb-loc...
но это вариант через жопу в целом как-то.
Ответ написан
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
Показывайте промокод юзеру, только после того, как он выдан. Или вообще генерируйте его при выдачи и записывайте в БД:
$secret = "some_secret_phrase";
$cod = md5($secret.Yii::$app->user->id);
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
SagePtr
@SagePtr
Еда - это святое
Как вариант, сначала пометить ближайший свободный промокод, а только потом его прочитать и отдать юзеру.
Ответ написан
Комментировать
@Hatik
Может подойдет триггер Before Update? в промокоде посмотреть наличие юзера, если есть то снова сделать селект и выдать другой промокод
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы