Доброго дня товарищи, пишу логику работы с балансом пользователя (пишу велосипед в целях своего обучения)
И не могу понять как правильно нужно работать с транзакциями, при симуляции, они все равно не срабатывают так, как я бы этого хотел.
Собственно суть вопроса, у меня есть метод
add_balance, он в свою очередь принимает аргумент, сумму для пополнения баланса пользователя, я беру из базы последнюю актуальную запись баланса и хочу к этому балансу добавить новую сумму.
Собственно как решить проблему одновременных транзакций (обращений в базу)?
Тестировал разными способами, в конечном итоге все равно баланс в базе данных сбивается после одновременных обращений к базе. Попросту в момент второго одновременного запроса, баланс уже изменен, и второй запрос работает по сути с предпоследней строкой, а не с последней, то есть уже с неактуальной.
Собственно как быть? Вот мой код, упростил и убрал все лишнее для вашего удобства.
public function add_balance($add_balance){
$transaction = ORM::get_db()->beginTransaction();
if($transaction){
//Получаю объект с вктуальным балансом
$LAST_TR = ORM::forTable('transactions')->where('user_id', UID)->orderByDesc('time')->findOne();
$last_balance = $LAST_TR->balance;
$TR = ORM::forTable('transactions')->create();
$TR->user_id = UID;
$TR->setExpr('time', 'NOW()');
$TR->balance = $last_balance + $add_balance;
$TR->new_balance = $add_balance;
$TR->old_balance = $last_balance;
$TR->save();
ORM::get_db()->commit();
}else{
ORM::get_db()->rollBack();
echo 'ОШИБКА: Уже выполняется другая транзакция';
}
}
PS.
Использую библиотеку idiOrm для работы с базой данных, в данной ОРМ нет своих методов для работы с транзакциями, есть только возможность вызова стандартных методов PDO
ORM::get_db()->beginTransaction(); // Равносильно PDO::beginTransaction();
ORM::get_db()->commit(); // Равносильно PDO::commit();
ORM::get_db()->rollBack(); // Равносильно PDO::rollBack();