I have this:
$scCost = $row["gpsc"];
mysql_query("
UPDATE member_profile
SET points = points-$scCost
WHERE user_id = '".mysql_real_escape_string($userid)."'
") or die(mysql_error());
That takes do the user´s points - scCost.
How do i check if the user can afford it or not? So, if the user has 30 and the $scCost is 40..
You can do this atomically by adding an extra condition to the query and using mysql_affected_rows()
:
$scCost = $row["gpsc"];
$user_id = mysql_real_escape_string($user_id);
$sql = <<<END
UPDATE member_profile
SET points = points - $scCost
WHERE user_id = $user_id
AND points >= $scCost
END;
mysql_query($sql);
if (mysql_affected_rows() > 0) {
// they can afford it
}
This is substantially better than doing a SELECT
followed by an UPDATE
, which introduces a race condition.
Caveat: mysql_affected_rows()
returns the number of rows that were changed. This is important to understand. If you pass 0 cost into this query you end up with:
UPDATE member_profiles SET points = points - 0 ...
mysql_affected_rows()
will always return 0 in that instance because no rows where changed. So if 0 cost is a valid case, you need to filter this and not bother running the query at all.
Also this works well if you're updating one row but it gets a little more difficult if you want to modify several rows at once. Then you get into questions like:
You may be best off doing one UPDATE
at a time even though this normally isn't the recommended approach and certainly won't scale to thousands of updates at once.