好吧,假设我们有bank_account
表。有一行名为money
。它有2000个价值。我们有两个人试图撤回这笔钱,我们假设他们可以这样做。那么,他们有可能同时这样做吗?例如。有一个简化的代码:
$all_money = get_value('money', 'bank_account); //lets suppose thats a function how we get value money from bank_account table
if($all_money > 0)
{
//here is a code where those money are being withdrawed from bank_account and inserting into the person's account
}
如果这两个人同时获得2,000,那么这意味着该条款if($all_money > 0)
将被执行,并且两个玩家将获得2,000并且bank_account将具有-2,000的金钱价值。那么,有可能发生吗?如果是,那我该如何保护呢?谢谢。
答案 0 :(得分:6)
在访问表格之前执行此操作:
LOCK TABLE table_name READ;
这将锁定表格。完成工作后,请致电:
UNLOCK TABLES;
答案 1 :(得分:3)
与信念相反,SQL语句被接收并放入队列中进行处理。它们不会同时执行。
发生什么取决于业务规则 - 如果银行账户允许透支,第二个请求将成功(假设足够大的透支)。否则,第二个请求将失败。
答案 2 :(得分:2)
我认为一种方法是使用transactions。当事务开始时,表将被锁定。它实际上与Cristian提出的相似。
答案 3 :(得分:1)
innodb中的交易将帮助您。记得阅读你的mysql版本,因为它们早先被窃听过。
答案 4 :(得分:1)
非常陈规定型的例子是:
DELIMITER //
CREATE PROCEDURE do_banktransfer(
IN transfer_amount INT,
IN from_account INT,
IN to_account INT,
OUT success INT)
BEGIN
START TRANSACTION;
UPDATE account SET balance = balance - transfer_amount WHERE id = from_account;
UPDATE account SET balance = balance + transfer_amount WHERE id = to_account;
SELECT balance INTO cur_balance FROM account WHERE id = from_account;
IF cur_balance < 0 THEN
SET success = 0;
ROLLBACK;
ELSE
SET success = 1;
COMMIT;
END IF;
END;//
答案 5 :(得分:0)
我认为您担心连接到数据库的两个独立线程和一个带有绘图资金的线程,而另一个执行基于先前读取的余额的代码。
在这种情况下,你应该在查询余额之前应用一个读锁(如Christian所说),并在[代码片段]中释放锁定if语句已经结束。
如果你的线程仍然有锁定,你可能会遇到问题,所以你需要一些精简的bash脚本来杀死东西;)