0

我在 PHP / MySQL 中有一段代码,看起来有点像:

foreach item
    try
        BEGIN
        update table 1, throw if failed
        update table 2, throw if failed
        update table 3, throw if failed
        etc. etc. etc.
        COMMIT
        print "COMMITTING"
    catch
        ROLLBACK
        print "ROLLING BACK"
    end try
end foreach

我遇到的问题是,我从每次迭代中始终收到“COMMITTING”消息,但有时(似乎是随机的),除了最后一个总是提交的更新之外,没有任何更新会提交。

所有表都是 InnoDB。有谁知道可能是什么问题?

编辑:这是代码的简化版本,希望它足以根除问题吗?

foreach($auctions as $a) {  

    try {

        mysql_query("BEGIN");   
        $items = fetchAll("SELECT * FROM users_auctions_items WHERE amount > 0 AND auction = {$a['id']}");
        $highBid = fetchOne("SELECT * FROM users_auctions_bids WHERE auction = {$a['id']} AND status = 0 LIMIT 1");

        if($highBid === false) {

            echo "No high bid, returning items to {$a['user']}\n";
            $recipientId = $a['user'];

        } else {

            $recipientId = $highBid['user'];
            echo "High bid by {$recipientId}\n";
            echo "Giving {$highBid['amount']} gold to {$a['user']}...\n";   
            mysql_query("UPDATE users SET gold = gold + {$highBid['amount']} WHERE id = {$a['user']}");
            if(mysql_affected_rows() != 1) throw new Exception();

        }

        if($items) {
            foreach($items as $i) {
                echo "Giving {$recipientId} item #{$i['item']} (x{$i['amount']})...\n";
                mysql_query("INSERT INTO users_inventory (user, item, amount) 
                    VALUES ({$recipientId}, {$i['item']}, {$i['amount']}) 
                    ON DUPLICATE KEY UPDATE amount = amount + {$i['amount']}");
                if(mysql_affected_rows() < 1) throw new Exception();
            }
        }

        mysql_query("UPDATE users_auctions SET status = 2 WHERE id = {$a['id']}");
        if(mysql_affected_rows() != 1) throw new Exception();

        mysql_query("COMMIT");
        echo "Committing\n";

    } catch(Exception $e) {

        echo "Rolling back\n";              
        mysql_query("ROLLBACK");

    }

}

更具体地说:这由 cron 每隔几分钟运行一次,并且应该运行所有未完成的拍卖并分发商品 - 之后,它将拍卖设置为完成。尽管日志说它运行良好并且它找到了正确的商品和用户,但它偶尔会更新拍卖以完成而不分配资产。

如果我将拍卖重置为不完整并让 cron 再次运行,它通常会毫无问题地完成(有时我必须将其重置 2-3 次)。

4

0 回答 0