数据库事务部分提交

时间:2012-08-03 09:47:15

标签: php mysql

我在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次)。

0 个答案:

没有答案