簡體   English   中英

我應該怎么做才能使MySQL事務在我的代碼中起作用?

[英]What should I do to make MySQL transactions work in my code?

無論是否成功執行來自事務的所有查詢,我的查詢都可以正常工作。

$this->mysqli->autocommit(FALSE);

$query = $this->mysqli->real_escape_string("INSERT INTO `product` (`name`, `price`) VALUES (?,?)");
            $prod = $this->mysqli->prepare($query);
            $prod->bind_param("ss", $name,$price);
            $prod->execute();

$query = $this->mysqli->real_escape_string("INSERT INTO `member` (`user`, `address`) VALUES (?,?)");
            $prod = $this->mysqli->prepare($query);
            $prod->bind_param("ss", $user,$address);
            $prod->execute();

$query = $this->mysqli->real_escape_string(" SOME BAD WRITTEN QUERY") ;
            $prod = $this->mysqli->prepare($query);
            $prod->execute();


if (!$this->mysqli->commit())
{
    print("\nTransaction commit failed\n");
    $this->mysqli->rollback();
}
$this->mysqli->autocommit(TRUE);

這段代碼正在起作用,並插入了前兩個查詢,當然在第三個查詢處中斷。

但是事務是行不通的,無論它將什么插入所有有效的查詢,我只想在所有三個查詢都正確完成的情況下插入。

我使用INNODB引擎和PHP 5.5

自禁用autocommit以來,隱式啟動事務后,MySQL 不會在內部跟蹤您執行的語句的成功狀態。 那是作為程序員的工作。 因此,即使“ SOME BAD WRITTEN QUERY失敗了,前兩個失敗也可以提交。

您必須測試每個對象是否成功,並相應地commit()rollback()

注意:你應該叫real_escape_string()的SQL語句。 它可能有害,對於准備好的語句字符串絕對不是必需的。

$this->mysqli->autocommit(FALSE);

$query = "INSERT INTO `product` (`name`, `price`) VALUES (?,?)";
$prod = $this->mysqli->prepare($query);
$prod->bind_param("ss", $name,$price);

// Store success/fail in a variable (returns TRUE on success)
$success1 = $prod->execute();

$query = "INSERT INTO `member` (`user`, `address`) VALUES (?,?)";
$prod = $this->mysqli->prepare($query);
$prod->bind_param("ss", $user,$address);

// Store success/fail in a variable (returns TRUE on success)
$success2 = $prod->execute();

$query = " SOME BAD WRITTEN QUERY";
$prod = $this->mysqli->prepare($query);

// Store success/fail in a variable (returns FALSE on failure)
$success3 = $prod->execute();

// Now check if all 3 succeeded and commit() if they did
if ($success1 && $success2 && $success3)
{
  $this->mysqli->commit();
}
// Or rollback() if they didn't
else
{
    print("\nTransaction commit failed\n");
    $this->mysqli->rollback();
}
$this->mysqli->autocommit(TRUE);

最后的筆記。 如果僅對單個事務禁用autocommit ,然后重新啟用它,請考慮僅使autocommit處於啟用狀態,並明確地開始和結束事務。 而不是調用$this->mysqli->autocommit(false)之后再調用$this->mysqli->autocommit(false) $this->mysqli->autocommit(true); ,只需致電

// Don't disable autocommit
// Start it...
$this->mysqli->begin_transaction();
// Do your 3 queries as above and test for success
// Then commit or rollback
$this->mysqli->commit();
// (or rollback)
// Now, no need to re-enable auto-commit

如果您的應用程序將使用大量事務,則必須禁用autocommit 您需要在每個操作之后顯式地commit() ,但我不會禁用它只是在一個事務之后重新啟用它。

關於DDL語句的說明-MySQL無法回滾DDL語句,並且我相信調用一個中間事務將導致所有先前的語句都被提交,即使您尚未顯式調用commit() 因此,如果要從代碼中發出CREATE,ALTER,DROP語句,請當心。 它們不能與事務一起使用。

正如@ gloomy.penguin所說,在發送第一個事務之前,需要先mysqli->begin_transaction()然后在發送mysqli->commit()之前。

除非您有更多稍后提交的代碼,否則禁用自動提交然后啟用自動提交是不必要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM