function deleteOrder($id, $ownerId) { $orderConnection = mappedConnection('orders'); $userConnection = mappedConnection('users'); $price = findOrderPriceById($orderConnection, $id, $ownerId); if (!$price) { return false; } $sqlOrders = 'UPDATE orders SET deleted = TRUE WHERE id = ' . (int) $id . ' AND done_by IS NULL AND deleted IS FALSE;'; $sqlUsers = 'UPDATE users SET cash = cash + ' . $price . ' WHERE id = ' . $ownerId . ';'; if ($orderConnection === $userConnection) { mysqli_begin_transaction($orderConnection); mysqli_query($orderConnection, $sqlOrders); if ($result = (bool) mysqli_affected_rows($orderConnection)) { mysqli_query($orderConnection, $sqlUsers); mysqli_commit($orderConnection); return true; } mysqli_rollback($orderConnection); return false; } else { $result = false; $uuid = uniqid('', false); $transactionOrder = '\'' . $uuid . '\', \'oi\''; $transactionUser = '******'' . $uuid . '\', \'ui\''; mysqli_query($userConnection, 'DO GET_LOCK(\'' . $uuid . '-u\', 1);'); mysqli_query($orderConnection, 'DO GET_LOCK(\'' . $uuid . '-o\', 1);'); // стартуем транзакцию на базе с заказами mysqli_query($orderConnection, 'XA START ' . $transactionOrder . ';'); // удаляем заказ mysqli_query($orderConnection, $sqlOrders); $completed = mysqli_affected_rows($orderConnection); mysqli_query($orderConnection, 'XA END ' . $transactionOrder . ';'); // если получилось удалить if ($completed) { mysqli_query($userConnection, 'XA START ' . $transactionUser . ';'); mysqli_query($userConnection, $sqlUsers); mysqli_query($userConnection, 'XA END ' . $transactionUser . ';'); // подготавиливаем обе транзакции if (mysqli_query($orderConnection, 'XA PREPARE ' . $transactionOrder . ';')) { if (mysqli_query($userConnection, 'XA PREPARE ' . $transactionUser . ';')) { // пытаемся закоммитить удаление заказа if (mysqli_query($orderConnection, 'XA COMMIT ' . $transactionOrder . ';')) { // плюсуем деньги, если в этот момет БД упала, то коммитим при поднятии. mysqli_query($userConnection, 'XA COMMIT ' . $transactionUser . ';'); $result = true; } else { // если что-то пошло не так, откатываем mysqli_query($userConnection, 'XA ROLLBACK ' . $transactionUser . ';'); } } else { mysqli_query($orderConnection, 'XA ROLLBACK ' . $transactionOrder . ';'); } } else { mysqli_query($userConnection, 'XA ROLLBACK ' . $transactionUser . ';'); } } else { // коммитим, изменений все равно нет. mysqli_query($orderConnection, 'XA COMMIT ' . $transactionOrder . ' ONE PHASE;'); } mysqli_query($userConnection, 'DO RELEASE_LOCK(\'' . $uuid . '-u\');'); mysqli_query($orderConnection, 'DO RELEASE_LOCK(\'' . $uuid . '-o\');'); return $result; } }
function completeOrder($id, $userId) { $id = (int) $id; $userId = (int) $userId; $userConnection = mappedConnection('users'); $orderConnection = mappedConnection('orders'); $price = findOrderPriceById($orderConnection, $id, $userId); if (!$price) { return false; } $commission = calculateCommission($price); $reward = $price - $commission; $sqlOrders = 'UPDATE orders SET done_by = ' . $userId . ', commission = ' . $commission . ' WHERE id = ' . $id . ' AND done_by IS NULL AND orders.deleted IS FALSE;'; $sqlUsers = 'UPDATE users SET cash = cash + ' . $reward . ' WHERE id = ' . $userId . ';'; if ($userConnection === $orderConnection) { mysqli_begin_transaction($orderConnection); mysqli_query($orderConnection, $sqlOrders); if ($result = (bool) mysqli_affected_rows($orderConnection)) { mysqli_query($orderConnection, $sqlUsers); mysqli_commit($orderConnection); return true; } mysqli_rollback($orderConnection); return false; } else { $uuid = uniqid('', false); // Лочим uuid, что бы скрипт поднятия оторваных транзакций не мешал ;) mysqli_query($userConnection, 'DO GET_LOCK(\'' . $uuid . '-u\', 1);'); mysqli_query($orderConnection, 'DO GET_LOCK(\'' . $uuid . '-o\', 1);'); $transactionOrder = '\'' . $uuid . '\', \'oc\''; $transactionUser = '******'' . $uuid . '\', \'uc\''; // стартуем транзакцию на базе с заказами mysqli_query($orderConnection, 'XA START ' . $transactionOrder . ';'); // помечаем заказ выполненым mysqli_query($orderConnection, $sqlOrders); $completed = mysqli_affected_rows($orderConnection); mysqli_query($orderConnection, 'XA END ' . $transactionOrder . ';'); $result = false; // если получилось пометить как выполненое if ($completed) { mysqli_query($userConnection, 'XA START ' . $transactionUser . ';'); mysqli_query($userConnection, $sqlUsers); mysqli_query($userConnection, 'XA END ' . $transactionUser . ';'); // подготавиливаем обе транзакции if (mysqli_query($orderConnection, 'XA PREPARE ' . $transactionOrder . ';')) { if (mysqli_query($userConnection, 'XA PREPARE ' . $transactionUser . ';')) { // пытаемся закоммитить изменения заказа if (mysqli_query($orderConnection, 'XA COMMIT ' . $transactionOrder . ';')) { // плюсуем деньги, если в этот момет БД упала, то коммитим при поднятии. mysqli_query($userConnection, 'XA COMMIT ' . $transactionUser . ';'); $result = true; } else { // если что-то пошло не так, пробуем откатить mysqli_query($userConnection, 'XA ROLLBACK ' . $transactionUser . ';'); } } else { mysqli_query($orderConnection, 'XA ROLLBACK ' . $transactionOrder . ';'); } } else { mysqli_query($userConnection, 'XA ROLLBACK ' . $transactionUser . ';'); } } else { // коммитим, изменений все равно нет. mysqli_query($orderConnection, 'XA COMMIT ' . $transactionOrder . ' ONE PHASE;'); } mysqli_query($userConnection, 'DO RELEASE_LOCK(\'' . $uuid . '-u\');'); mysqli_query($orderConnection, 'DO RELEASE_LOCK(\'' . $uuid . '-o\');'); return $result; } }