Problem with duplicate mysql record

Asked

Viewed 199 times

1

I have a script that receives requests from the free market when there is some update on a request.

When an order is placed, the free market sends 5 to 10 requests to that script at about the same time (don’t ask me why it sends so many requests at the same time, because they are all the same), and I enter in my bank only one of them.

The problem is basically in the lines below, which check whether the request has already been inserted in the table of the bank. ($obj_sql is a simple mysql handler, and I think the problem is not in it.)

$jatemped = $obj_sql->Get("select count(ped_id) from pedidos where mel_order='$id_order'");
if ($jatemped===0) {
   $obj_sql->Query("insert into pedidos (mel_order) values ('".$id_order."')");
}

the mel_order field is not unique as it can contain records in the requested table with this blank field.

The problem is that sometimes Insert is duplicated by a second request of the script, with the same $id_order in the mel_order field.

Is there some sort of cache between the Insert and the select of the next script execution that it cannot see the Insert that has just been made?

How can I fix this?

  • how are these free market requests? can post?

  • What can help you is to use transactions, which are available in Mysql for the Innodb Engine. With a transaction it is possible to lock the table or rows while writing operations are taking place in the database. Documentation: https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-model.html

  • Probably a Race Condition, the two requests arrived at the same point at the same time, so for both the $jatemped is 0, this is something predictable and somewhat logical since there is nothing that blocks. Ideally you use UNIQUE, the rest is gambiarra. One of the other tricks is to use SELECT ... FOR UPDATE within a TRANSCATION or execute a INSERT SELECT ... WHERE NOT EXISTS .... also within the transaction.

  • Try changing count(ped_id) for only ped_id and in the IF comparison, change to if (mysql_fetch_array($jatemped) === false) {. I find it unnecessary to count the number of records with count(), since you just want to know whether or not the registration exists with the $id_order. I think it’s better to get a boolean (maybe faster until).

  • @Diegolela the requests are post with a json in the body. I think this is not the problem, because I can identify the contents correctly.. the point is that the calls are at the same time, and first select with Count can not identify that another transaction almost at the same time already inserted.

  • @Davidsamm will make this change to see if it helps too

  • @Is it possible to have a single key field only when the field is not null or blank? because this field exists several records with the blank value for the field mel_order.

  • @Rodrigovicentin, yes. By default inclusive, "For all Engines, a UNIQUE index Permits Multiple NULL values for Columns that can contain NULL.", see the documentation. As long as it is actually NULL (and table allows NULL) it can have multiple NULL even in UNIQUE.

Show 3 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.