請記住,MyISAM 資料表不支援回滾。
我花了一個下午瘋狂地尋找程式碼中的錯誤 - 但實際上程式碼一直以來都沒問題
(PHP 5, PHP 7, PHP 8)
mysqli::rollback -- mysqli_rollback — 復原目前交易
物件導向風格
程序風格
將資料庫目前的交易回滾。
mysql
僅限程序式風格:由 mysqli_connect() 或 mysqli_init() 返回的 mysqli 物件。
flags
MYSQLI_TRANS_COR_*
常數的位元遮罩。
name
如果提供,則會執行 ROLLBACK/*name*/
。
如果啟用了 mysqli 錯誤報告 (MYSQLI_REPORT_ERROR
) 且請求的操作失敗,則會產生警告。此外,如果模式設定為 MYSQLI_REPORT_STRICT
,則會改為拋出 mysqli_sql_exception。
版本 | 說明 |
---|---|
8.0.0 |
name 現在可以為 null。 |
請參閱 mysqli::begin_transaction() 範例。
注意:
此函式不適用於非交易式表格類型(例如 MyISAM 或 ISAM)。
這是一個說明回滾和提交函式強大功能的範例。
假設您要確保所有查詢都必須在將資料寫入資料庫之前正確執行。
程式碼如下
<?php
$all_query_ok=true; // 控制變數
// 執行 4 次插入,最後一次會產生錯誤
// 如果至少有一次查詢返回錯誤,就改變控制變數的值
$mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (200)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (300)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false; // 主鍵值重複
// 現在測試控制變數
$all_query_ok ? $mysqli->commit() : $mysqli->rollback();
$mysqli->close();
?>
希望有幫助!
如果您使用存儲點 - 例如 savepoint($foo) - 請注意不要嘗試使用 rollback(0, $foo) 回滾到存儲點,因為它會執行 "ROLLBACK /* $foo */" 而不是 "ROLLBACK TO `$foo`”。
手冊頁面清楚地說明了這一點,但很容易被忽略。
請改用:$mysqli->query("ROLLBACK TO `$foo`");
關於自動遞增 ID 和回滾的注意事項。
當使用事務並插入到包含具有自動遞增 ID 的列的表格時,即使事務已回滾,ID 也會遞增。
如果執行大量的回滾,這可能會佔用大量的 ID。
範例
<?php
$mysqli = new mysqli("localhost", "gugbageri", "gugbageri", "gugbageri");
/* 檢查連線 */
if (mysqli_connect_errno()) {
printf("連線失敗: %s\n", mysqli_connect_error());
exit();
}
/* 關閉自動提交 */
$mysqli->autocommit(FALSE);
/* 我們建立一個測試表,包含一個自動遞增的主鍵欄位和一個內容欄位*/
$mysqli->query("CREATE TABLE TestTable ( `id_column` INT NOT NULL AUTO_INCREMENT , `content` INT NOT NULL , PRIMARY KEY ( `id_column` )) ENGINE = InnoDB;");
/* 提交新建的表格 */
$mysqli->commit();
/* 我們插入一列資料 */
$mysqli->query("INSERT INTO TestTable (content) VALUES (99)");
/* 我們提交插入的列 */
$mysqli->commit();
/* 我們再插入三列資料 */
$mysqli->query("INSERT INTO TestTable (content) VALUES (99)");
$mysqli->query("INSERT INTO TestTable (content) VALUES (99)");
$mysqli->query("INSERT INTO TestTable (content) VALUES (99)");
/* 我們執行回滾 */
$mysqli->rollback();
/* 我們插入一列資料 */
$mysqli->query("INSERT INTO TestTable (content) VALUES (99)");
/* 我們提交插入的列 */
$mysqli->commit();
if ($result = $mysqli->query("SELECT id_column FROM TestTable")) {
while($row = $result->fetch_row()) {
printf("ID: %d.\n", $row[0]);
}
/* 釋放結果 */
$result->close();
}
/* 刪除表格 TestTable */
$mysqli->query("DROP TABLE TestTable");
$mysqli->close();
?>
這將輸出
ID: 1.
ID: 5.