Как задержать SELECT во время INSERT при работе с моделями в Laravel?

Приветствую!
Столкнулся с проблемой во время проверки наличия строки в таблице, когда срабатывают два события чтение-запись почти в одно и тоже время.
В теле метода идёт проверка на "недавние" записи в таблице, если таких не будет найдено, то можно вставлять в таблицу. Тогда при следующей проверке (событии извне) будет найдена "недавняя" запись и новый INSERT не произойдет.
Но когда два события происходят в интервале до 50-150 мс, вторая проверка SELECT показывает, что "недавних" не было, потому что запись по первому событию ещё идёт (моё предположение). В результате сего — добавляется две строки.
Тело метода, где идёт вызов метода проверки и вставка:
$handle = new Handle;
$handle->date = Carbon::now();
$handle->oid = $id;
$next_id = Controller::getNextID();
if($next_id > 0)
	$handle->save();

Метод с проверкой
$handle = Handle::select(DB::raw("MAX(date) as date"))->where("oid", $id)->first(); // Найти последнюю дату записи
if($handle)
{			
	$date = Carbon::parse($handle->date)->addMinutes(15);

	if($date < $now) // Если с момента последней записи прошло >15 минут
	return $id; // $id всегда >0
}
return 0;


Использую репликацию MASTER-SLAVE, но модель Handle принудительно работает на MASTER'e.

Подскажите пожалуйста, в какую сторону копать и стоит ли оборачивать что-нибудь в:
DB::beginTransaction();
stmt...
DB::commit();
  • Вопрос задан
  • 138 просмотров
Решения вопроса 1
Melkij
@Melkij
PostgreSQL DBA
Типичный race condition. Для исправления вам необходимо найти некоторое место для сериализации транзакции. Транзакция, разумеется, нужна. Но и некоторый ресурс для сериализации этих транзакций нужен.
Например, через добавление подходящего уникального ключа (чтобы конкурентный insert споткнулся на нём), advisory lock, serializable isolation level не должен разрешить такое закоммитить.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Alex_Wells
@Alex_Wells
PHP/TS/Kotlin developer
Оборачиваешь в транзакцию, внутри все что хочешь вытягиваешь с нужными локами (апдейт лок, например) и работаешь с этим.
Ответ написан
Ваш ответ на вопрос

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

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