PHP Conference Japan 2024

mysqli::begin_transaction

mysqli_begin_transaction

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

mysqli::begin_transaction -- mysqli_begin_transaction開始一個事務

說明

物件導向風格

public mysqli::begin_transaction(int $flags = 0, ?string $name = null): bool

程序式風格

mysqli_begin_transaction(mysqli $mysql, int $flags = 0, ?string $name = null): bool

開始一個事務。需要 InnoDB 引擎(預設為啟用)。關於 MySQL 事務如何運作的更多細節,請參閱 » https://mysqldev.dev.org.tw/doc/mysql/en/commit.html

參數

mysql

僅限程序式風格:由 mysqli_connect()mysqli_init() 返回的 mysqli 物件

flags

有效的旗標為

name

事務的儲存點名稱。

返回值

成功時返回 true,失敗時返回 false

更新日誌

版本 說明
8.0.0 name 現在可以為 null。

範例

範例 #1 mysqli::begin_transaction() 範例

物件導向風格

<?php

/* 若發生錯誤,告知 mysqli 拋出例外 */
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* 資料表引擎必須支援交易 */
$mysqli->query("CREATE TABLE IF NOT EXISTS language (
Code text NOT NULL,
Speakers int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
);

/* 開始交易 */
$mysqli->begin_transaction();

try {
/* 插入一些值 */
$mysqli->query("INSERT INTO language(Code, Speakers) VALUES ('DE', 42000123)");

/* 嘗試插入無效的值 */
$language_code = 'FR';
$native_speakers = 'Unknown';
$stmt = $mysqli->prepare('INSERT INTO language(Code, Speakers) VALUES (?,?)');
$stmt->bind_param('ss', $language_code, $native_speakers);
$stmt->execute();

/* 如果程式碼執行到此處沒有錯誤,則提交資料庫中的資料 */
$mysqli->commit();
} catch (
mysqli_sql_exception $exception) {
$mysqli->rollback();

throw
$exception;
}

程序式風格

<?php

/* 告知 mysqli 如果發生錯誤則拋出例外 */
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$mysqli = mysqli_connect("localhost", "my_user", "my_password", "world");

/* 資料表引擎必須支援交易 */
mysqli_query($mysqli, "CREATE TABLE IF NOT EXISTS language (
Code text NOT NULL,
Speakers int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
);

/* 開始交易 */
mysqli_begin_transaction($mysqli);

try {
/* 插入一些值 */
mysqli_query($mysqli, "INSERT INTO language(Code, Speakers) VALUES ('DE', 42000123)");

/* 嘗試插入無效的值 */
$language_code = 'FR';
$native_speakers = 'Unknown';
$stmt = mysqli_prepare($mysqli, 'INSERT INTO language(Code, Speakers) VALUES (?,?)');
mysqli_stmt_bind_param($stmt, 'ss', $language_code, $native_speakers);
mysqli_stmt_execute($stmt);

/* 如果程式碼執行到此處沒有錯誤,則提交資料庫中的資料 */
mysqli_commit($mysqli);
} catch (
mysqli_sql_exception $exception) {
mysqli_rollback($mysqli);

throw
$exception;
}

注意事項

備註:

此函式不適用於非交易資料表類型(例如 MyISAM 或 ISAM)。

參見

新增備註

使用者貢獻的備註 2 則備註

8
Ral
6 年前
如果您使用 *確實* 支援「READ WRITE」和「READ ONLY」的 MariaDB 版本,卻收到類似「此伺服器版本不支援『READ WRITE』和『READ ONLY』。最低需要 5.6.5」的錯誤訊息,這是因為 mysqli 內部的檢查與 MariaDB 中允許與 Oracle MySQL 複製的 hack 衝突所致。

MariaDB 的伺服器版本號會以「5.5.5-」作為前綴,例如「5.5.5-10.3.7-MariaDB-1:10.3.7+maria~stretch」。這是因為 Oracle MySQL 會將「10」解讀為版本 1。已更新可辨識 MariaDB 的 MySQL 用戶端,會偵測並移除此前綴。

然而,mysqli.begin-transaction 的檢查會看到 5.5.5 的前綴,因此會失敗。

解決方法是在命令列上使用 --version 選項,為 MariaDB 指定一個沒有前綴的自訂版本字串。然後 mysqli.begin-transaction 就能如預期般運作。
1
PHP 專家
4 年前
MySQL 5.6 引入了 READ ONLY 模式,它會對您的交易套用最佳化,但僅限於預先知道不會修改任何資料表且不會發出任何鎖定的情況下才能套用。

在所有 5.6 以前的版本(包含 5.6)中,預設的存取模式都是 READ WRITE。從 MySQL 5.7 開始,系統會自動偵測適當的存取模式。因此,如果您的交易嘗試修改或鎖定資料表,它會自動使用 READ WRITE 模式;否則,它會使用 READ ONLY 模式,您的交易將受益於該模式帶來的最佳化,而無需明確宣告為 READ ONLY。

因此,只有在您使用 MySQL 5.6 且確定要使用 READ ONLY 模式時,才需要明確宣告存取模式。請注意,在 READ ONLY 模式下,任何嘗試修改資料表或發出鎖定的查詢都會失敗。暫存資料表仍然可以修改。

(版主:這篇文章應該取代我之前發布的關於這個主題的文章。謝謝。)
To Top