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://dev.mysqlserver.cn/doc/mysql/en/commit.html.

参数

mysql

仅限过程式风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象。

flags

有效的标志是

  • MYSQLI_TRANS_START_READ_ONLY: 以 "START TRANSACTION READ ONLY" 的方式启动事务。需要 MySQL 5.6 及更高版本。

  • MYSQLI_TRANS_START_READ_WRITE: 以 "START TRANSACTION READ WRITE" 的方式启动事务。需要 MySQL 5.6 及更高版本。

  • MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT: 以 "START TRANSACTION WITH CONSISTENT SNAPSHOT" 的方式启动事务。

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)。

参见

添加笔记

用户贡献笔记 4 个笔记

Ral
6 年前
如果你在支持“READ WRITE”和“READ ONLY”的 MariaDB 版本中遇到以下错误:“This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required”,这是由于 mysqli 内部检查与 MariaDB 中允许与 Oracle MySQL 进行复制的漏洞冲突造成的。

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 函数将按预期工作。
PHP Guru
4 年前
MySQL 5.6 引入了 READ ONLY 模式,该模式对你的事务应用优化,这些优化只能在它预先知道不会进行任何表修改且不会发出任何锁的情况下应用。

在包括 MySQL 5.6 在内所有版本中,默认访问模式为 READ WRITE。从 MySQL 5.7 开始,会自动检测适当的访问模式。因此,如果你的事务尝试修改或锁定表,它将自动使用 READ WRITE 模式,否则它将使用 READ ONLY 模式,你的事务将受益于由此带来的优化,而不必显式声明为 READ ONLY。

因此,只有在你使用 MySQL 5.6 并且确定需要 READ ONLY 模式时,才需要显式声明访问模式。请注意,在 READ ONLY 模式下尝试修改表或发出锁的任何查询都将失败。临时表仍然可以修改。

(版主。这篇文章应该替换我之前发布的关于该主题的文章。谢谢。)
VasK@hapir
5 年前
Ral 的上述答案对我们有效,非常感谢。以下是我们如何实现提出的解决方法:

警告:mysqli_begin_transaction():此服务器版本不支持“READ WRITE”和“READ ONLY”。需要最低版本 5.6.5

我们将以下行追加到 /etc/my.cnf 并重新启动 MySQL 服务器

version=10.2.19-MariaDB
Luc
7 年前
对于 PHP<5.5

mysqli_query($db, "START TRANSACTION");
To Top