Ich habe einige Frage ... Beispiel: ein Benutzer etwas für seine USDPHP/MySQL - wie zwei Anfragen zu verhindern * Update
- prüfen sein USD Gleichgewicht
- Abzüglich des USD kaufen wird von seinem Konto
- eine Bestellung aufgeben - seine USD > Auftragswarteschlange
- Benutzer erhält seine Position und der andere bekommt
können sagen, die Benutzer macht 5 Anfragen in der gleichen Sekunde (sehr schnell). So ist es möglich (und passieren), dass 5 Anfragen laufen. Er hat nur Geld, um nur aus 1 Anfrage zu kaufen. Jetzt sind die Anfragen so schnell, dass das Skript sein Guthaben überprüft, aber nicht so schnell ist, dass es das Geld von seinem Konto abzieht. Also werden die Anfragen zweimal passieren! Wie löst man es?
ich LOCK in MySQL verwenden, bevor ich den Prozess zu starten:
- IS_FREE_LOCK - Check gibt es eine Sperre für diesen Benutzer, wenn nicht -> 2.
- GET_LOCK - setzt das Schloss
- das machen Auftrag/Transaktion
- RELEASE_LOCK - die Verriegelung
Aber das ist nicht wirklich funktioniert. Gibt es eine andere Art und Weise?
function lock($id) {
mysql_query("SELECT GET_LOCK('$id', 60) AS 'GetLock'");
}
function is_free($id) {
$query = mysql_query("SELECT IS_FREE_LOCK('$id') AS 'free'");
$row = mysql_fetch_assoc($query);
if($row['free']) {
return true;
} else {
return false;
}
}
function release_lock($id) {
mysql_query("SELECT RELEASE_LOCK('$id')");
}
function account_balance($id) {
$stmt = $db->prepare("SELECT USD FROM bitcoin_user_n WHERE id = ?");
$stmt->execute(array($id));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row['USD'];
}
if(is_free(get_user_id())) {
lock(get_user_id());
if(account_balance(get_user_id()) < str2num($_POST['amount'])) {
echo "error, not enough money";
} else {
$stmt = $db->prepare("UPDATE user SET USD = USD - ? WHERE id = ?");
$stmt->execute(array(str2num($_POST['amount']), get_user_id()));
$stmt = $db->prepare("INSERT INTO offer (user_id, type, price, amount) VALUES (?, ?, ?, ?)");
$stmt->execute(array(get_user_id(), 2, str2num($_POST['amount']), 0));
}
aktualisieren die Transaktion Funktion mit SELECT Getestet ... FOR UPDATE
$db->beginTransaction();
$stmt = $db->prepare("SELECT value, id2 FROM test WHERE id = ? FOR UPDATE");
$stmt->execute(array(1));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($row['value'] > 1) {
sleep(5);
$stmt = $db->prepare('UPDATE test SET value = value - 5 WHERE id = 1');
$stmt->execute();
$stmt = $db->prepare('UPDATE test SET value = value + 5 WHERE id = 2');
$stmt->execute();
echo "did have enough money";
} else {
echo "no money";
}
$db->commit();
[** Bitte verwenden Sie nicht mysql_ * 'Funktionen im neuen Code **] (http://bit.ly/phpmsql). Sie werden nicht mehr gewartet [und sind offiziell veraltet] (http://j.mp/XqV7Lp). Siehe die [** rote Box **] (http://j.mp/Te9zIL)? Erfahren Sie mehr über [* prepared statements *] (http://j.mp/T9hLWi) und verwenden Sie [PDO] (http://php.net/pdo) oder [MySQLi] (http://php.net/) mysqli) - [dieser Artikel] (http://j.mp/QEx8IB) wird Ihnen helfen zu entscheiden, welche. – Kermit
Jeder weiß, was das bedeutet: "Der Benutzer wird sein Gegenstand und der andere wird sein USD"? Meinten sie "bekommt" anstatt "wird"? – ESRogs
Wie ist es überhaupt * möglich * eine Online-Trading-Site zu betreiben, ohne auch nur die * Grundlagen * über Transaktionen zu kennen?!? – Massimo