PHP PDO MySQL 交易未执行

PHP PDO MySQL transactions not executed

我正在努力实施 PHP 和 MySQL 交易。该脚本通过阻塞重新发送队列接收 SQL 语句以及一些绑定参数。所有内容都传递给一个函数 'do_transaction',该函数跟踪收到的语句数。

我用 PdoDebugger 调试了 PDO 语句(在它被处理之后)并且输出是正确的:

UPDATE bla SET processed = 1, severity_ou1 = 'low', 
severity_ou2 = 'low', severity_ou3 = 'low', severity_ou4 = 'low',
severity_ou5 = 'low', saved = '1', hname = '1', sname = '1', if = '1',
v = '1', translated = 'blablabla.', filtered = 1, repeated = '1',
excessed = '1', eventfilterid = '212', building = '1', floor = '1'
WHERE id = '121614624'
global $batchcount;
$batchcount = 1;

while(true){
    $redis = new Redis();
    $redis->connect('xxx', xxx);
    $sqlbatch = $redis->blpop('xxx:xxx:sqlfiltermatch', 0);

    // blpop returns array: 0 has key, 1 has data.
    if(is_array($sqlbatch)){
        if(isJson($sqlbatch[1])){
            $batchstatements = array();
            $batchstatements[] = json_decode($sqlbatch[1], true);
            // Get statement and bindparams.
            $sqlstatement = $batchstatements[0]['statement'];
            $bindparams = $batchstatements[0]['bindparams'];
            // Replace empty bindparams.
            foreach($bindparams as $column => $value){
                if(is_null($value)){ $bindparams[$column] = '1'; }
                if(empty($value)){ $bindparams[$column] = '1'; }
            }
        }
        $batchcount++;
        do_transaction($sqlstatement, $bindparams, $batchcount);
    }
}

function do_transaction($sqlstatement, $bindparams){
    global $batchcount;
    if($batchcount >= 4){
       try {
            // Setup DB
            $db = new PDO('mysql:host=xxx;dbname=xxx;charset=utf8', 'xxx', 'xxx', array(PDO::ATTR_PERSISTENT => true, PDO::ATTR_AUTOCOMMIT => FALSE, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
            echo $db->getAttribute(PDO::ATTR_AUTOCOMMIT)."\n\n"; 
            $db->beginTransaction();
            $stmt = $db->prepare($sqlstatement);

            // Setup bindparams.
            foreach($bindparams as $column => $value){
                $stmt->bindParam(":$column", $value);
            }
            $stmt->execute() or die(print_r($stmt->errorInfo(), true));
            echo PdoDebugger::show($sqlstatement, $bindparams)."\n";
            $db->commit();

        } catch(PDOExecption $e){
            //$db->rollback();
            print_r("ERROR"); exit;              
        }
        $batchcount = 0;
    }

    $batchcount++;
}

我已经确定 AUTOCOMMIT = FALSE。 "do_transaction"哪里出错了?

以这种方式使用事务没有意义。 所以,让他们一个人呆着吧。

function do_query($db, $sqlstatement, $bindparams){
    $stmt = $db->prepare($sqlstatement);
    $stmt->execute($bindparams);
    return $stmt;
}

是您实际需要的所有代码。

这样用

$db = new PDO('mysql:host=xxx;dbname=xxx;charset=utf8', 'xxx', 'xxx',
    array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
);
while(true){
   // whatever redis code goes here
   do_query($db, $sqlstatement, $bindparams);
}

注意:如果你想让你的插入速度更快,你应该问一个标题为 "How to make inserts faster" 的问题,没有 "My transactions do not work"。

但是你插入交易的想法也是错误的。
单个事务(就业务逻辑而言)必须尽快写入数据库,而不干扰其他事务。意味着您永远不应该在单个数据库事务中耦合不同的业务逻辑事务。因为单个业务逻辑事务中的错误会破坏整个批次。所以——把它们分开写。