Supposing our accounts
table has a column called balance
, each transaction is logged in the transactions
table. Of course, we should verify there is sufficient funds prior to doing any transactions to sell products. Therefore, for performance purposes we should check the balance
column of the user, deduct the amount on a successful sale, and update his balance
.
However, if the user asynchronously bought 2 products, could not that potentially cause fraud? I've wrote a script that will deduct funds from an account and cloned it to another file. I executed both scripts at the same time and the results were surprising.
Deduct.php
<?php
//database connection...
$amount = 11;
$deducted = 0;
$blocked = 0;
for($i = 0; $i < 5000; $i++){
$sql = $dbh->prepare('SELECT balance FROM accounts WHERE id = ?');
$sql->execute(array(1));
while($u = $sql->fetch()){
$balance = $u['balance'];
$deduct = $balance - $amount;
if($deduct >= 0){
$sql2 = $dbh->prepare('UPDATE accounts SET balance = ? WHERE id = ?');
$sql2->execute(array($deduct,1));
echo $balance . ' -> ' . $deduct . "\n";
$deducted += $amount;
} else {
$blocked++;
}
}
}
echo 'Deducted: '.$deducted. "\n";
echo 'Blocked: '.$blocked;
Before running the scripts my balance
was 1000000. I've executed two processes of this script with different $amount
values.
Here are the results:
- Any alternative solutions to overcome this? I understand that logging each transaction and calculating the final balance is precise but is also intensive.