A
A
Alexander2019-07-11 10:16:59
MySQL
Alexander, 2019-07-11 10:16:59

How to delay SELECT during INSERT when working with models in Laravel?

Greetings!
I ran into a problem while checking for the presence of a row in a table, when two read-write events fire almost at the same time.
In the body of the method, there is a check for "recent" records in the table, if there are none, then they can be inserted into the table. Then at the next check (an event from outside) the "recent" record will be found and a new INSERT will not occur.
But when two events occur within 50-150ms interval, the second SELECT check shows that there were no "recent" ones, because the first event is still being recorded (my guess). As a result of this, two lines are added.
The body of the method, where the check method is called and the insertion is:

$handle = new Handle;
$handle->date = Carbon::now();
$handle->oid = $id;
$next_id = Controller::getNextID();
if($next_id > 0)
  $handle->save();

Method with validation
$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;

I use MASTER-SLAVE replication, but the Handle model is forced to work on the MASTER.
Please tell me in which direction to dig and whether it is worth wrapping something in:
DB::beginTransaction();
stmt...
DB::commit();

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Melkij, 2019-07-11
@MrLongMan

Typical race condition. To fix, you need to find some place to serialize the transaction. The transaction is, of course, necessary. But some resource is also needed to serialize these transactions.
For example, by adding a suitable unique key (so that a competitive insert stumbles on it), advisory lock , serializable isolation level should not allow such a commit.

A
Alex Wells, 2019-07-11
@Alex_Wells

You wrap it in a transaction, inside you pull everything you want with the necessary locks (update lock, for example) and work with it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question