This is one of the approaches available.
You need to use the InnoDB for your table. InnoDB supports row locking, so you donβt need to lock the entire table to UPDATE only one ROW associated with this user. (Locking the table will prevent other INSERT/UPDATE/DELETE operations from occurring, as a result of which they will have to wait until this LOCK table is released).
In InnoDB, you can achieve ROW LOCK when you execute a SELECT query using FOR UPDATE . (but in this you must use a transaction to achieve LOCK ). When you do SELECT ... FOR UPDATE in a transaction, mysql locks the selected row that you select until the transaction is completed. And suppose you make a SELECT ... FOR UPDATE query in your backend for user XXX, and at the same time, the interface makes the same query for the same XXX. The first request (from the backend) that was executed will block writing to the database, and the second request will wait for the completion of the first request, which may lead to some delay for the completion of the frontend request.
But for this script to work, you must specify both external and backend queries in the transaction, and both SELECT queries must have FOR UPDATE at the end.
So your code will look like this:
$transaction = 1000; mysqli_begin_transaction($conn); $getData = mysqli_fetch_array(mysqli_query($conn,"SELECT balance FROM tableA WHERE user='xxx' FOR UPDATE")); $balance = $getData["balance"] - $transaction; //10000 - 1000 = 9000 mysqli_query($conn,"UPDATE tableA SET balance='".$balance."' WHERE user='xxx'"); mysqli_commit($conn);
If this is your backend code, the external code should look very similar: start / complete transaction + FOR UPDATE .
One of the best FOR UPDATE is that if you need a query to LOCK certain row and do some calculations with this data in this scenario, but at the same time you need other queries that select the same row, and they DO NOT need the latest data on this line than you can just do these queries without a transaction and without FOR UPDATE at the end. That way, you will have the LOCKED line and other normal SELECTs that are read from it (of course, they will read the old information ... stored before the start of LOCK ).
source share