【发布时间】:2013-02-08 05:26:55
【问题描述】:
我有一个问题... 例如:用户会用他的美元买东西
- 查看他的美元余额
- 从他的账户中扣除美元
- 下订单 -> 订单队列
- 用户得到他的物品,另一个得到他的美元
假设用户在同一秒内发出 5 个请求(非常快)。 所以有可能(并且发生)5 个请求正在运行。 他只有从 1 个请求中购买的钱。现在的请求 太快了,脚本会检查他的余额,但不是很快,它会扣除 他账户里的钱。所以请求将通过两次! 如何解决?
在我开始进程之前,我在mysql中使用了LOCK:
- IS_FREE_LOCK - 如果没有,请检查该用户是否有锁 -> 2.
- GET_LOCK - 设置锁
- 下订单/交易
- RELEASE_LOCK - 释放锁
但这并没有真正起作用。还有其他方法吗?
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));
}
更新 用 SELECT ... 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();
【问题讨论】:
-
Please, don't use
mysql_*functions in new code。它们不再维护and are officially deprecated。看到red box?改为了解 prepared statements,并使用 PDO 或 MySQLi - this article 将帮助您决定哪个。 -
任何人都知道这是什么意思:“用户成为他的项目,另一个成为他的美元”?他们的意思是“得到”而不是“成为”吗?
-
在不了解交易的基础的情况下,如何可能经营一个在线交易网站?!?
标签: php transactions