0

I have a MySQL database and an online website (with PHP running on the backend).

If user A sends money to B, but B sends money to A in the same time, there is a race condition.

There are several other more complicated race conditions than just sending money (e.g. trading several items simultaneously for several other items - each item corresponding to a row in a MySQL table).

In PHP, is there a global lock I can use which I can refer to by a user's ID?

Pseudo code of what I want:

lock_acquire($user_A->id);
lock_acquire($user_B->id);

//do some sensitive stuff between user A and user B

lock_release($user_A->id);
lock_release($user_B->id);

Is there such a function in PHP?

Thanks in advance!

  • no, there is no global lock in php. each http request is a separate independent PHP process (or at least webserver child process), and there is not built-in synchronization between independent PHP processes. but all you really need to do is have BOTH of the php processes establish their own locks on the relevant tables. whichever request gets handled first will get through the database first, and the other request will simply wait. – Marc B Mar 02 '16 at 21:07
  • Thanks for the insight, but what about a hacky work-around, like making a MySQL table of locks? I can't think of many other ways. –  Mar 02 '16 at 21:13
  • then you'er stuck with having to lock THAT table to be sure that your lock inserts/updates/deletes don't get stomped on. exact same problem, just on different tables. just lock the relevant tables directly in your script, do your updates/inserts/selects, unlock the table, and move on. – Marc B Mar 02 '16 at 21:15
  • Honestly this is something you should be able to solve in a nicer way by using [Database Transactions](https://en.wikipedia.org/wiki/Database_transaction). Databases are designed to deal with these issues and they use smarter approaches than a global lock. [Some example](http://stackoverflow.com/questions/2708237/php-mysql-transactions-examples) – MartinS Mar 02 '16 at 21:34
  • A work around would be to add a column called `locked` and when you are doing those manipulations update it to `1`, when you are done change it back to `0`. Not pretty but it would work. – Pitchinnate Mar 02 '16 at 21:35

0 Answers0