mysqli::autocommit

mysqli_autocommit

(PHP 5, PHP 7, PHP 8)

mysqli::autocommit -- mysqli_autocommit打开或关闭自动提交数据库修改

说明

面向对象风格

public mysqli::autocommit(bool $enable): bool

过程式风格

mysqli_autocommit(mysqli $mysql, bool $enable): bool

打开或关闭数据库连接查询的自动提交模式。

要确定自动提交的当前状态,请使用 SQL 命令 SELECT @@autocommit

参数

mysql

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

enable

是否打开自动提交。

返回值

成功时返回 true,失败时返回 false

错误/异常

如果启用了 mysqli 错误报告 (MYSQLI_REPORT_ERROR) 并且请求的操作失败,则会生成警告。此外,如果模式设置为 MYSQLI_REPORT_STRICT,则会抛出 mysqli_sql_exception 而不是警告。

示例

示例 #1 mysqli::autocommit() 示例

面向对象风格

<?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->autocommit(false);

$result = $mysqli->query("SELECT @@autocommit");
$row = $result->fetch_row();
printf("Autocommit is %s\n", $row[0]);

try {
/* 准备插入语句 */
$stmt = $mysqli->prepare('INSERT INTO language(Code, Speakers) VALUES (?,?)');
$stmt->bind_param('ss', $language_code, $native_speakers);

/* 插入一些值 */
$language_code = 'DE';
$native_speakers = 50_123_456;
$stmt->execute();
$language_code = 'FR';
$native_speakers = 40_546_321;
$stmt->execute();

/* 提交数据库中的数据。这不会设置 autocommit=true */
$mysqli->commit();
print
"Committed 2 rows in the database\n";

$result = $mysqli->query("SELECT @@autocommit");
$row = $result->fetch_row();
printf("Autocommit is %s\n", $row[0]);

/* 尝试插入更多值 */
$language_code = 'PL';
$native_speakers = 30_555_444;
$stmt->execute();
$language_code = 'DK';
$native_speakers = 5_222_444;
$stmt->execute();

/* 设置 autocommit=true 将触发提交 */
$mysqli->autocommit(true);

print
"Committed 2 row in the database\n";
} 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_autocommit($mysqli, false);

$result = mysqli_query($mysqli, "SELECT @@autocommit");
$row = mysqli_fetch_row($result);
printf("Autocommit is %s\n", $row[0]);

try {
/* 准备插入语句 */
$stmt = mysqli_prepare($mysqli, 'INSERT INTO language(Code, Speakers) VALUES (?,?)');
mysqli_stmt_bind_param($stmt, 'ss', $language_code, $native_speakers);

/* 插入一些值 */
$language_code = 'DE';
$native_speakers = 50_123_456;
mysqli_stmt_execute($stmt);
$language_code = 'FR';
$native_speakers = 40_546_321;
mysqli_stmt_execute($stmt);

/* 提交数据库中的数据。这不会将 autocommit 设置为 true */
mysqli_commit($mysqli);
print
"Committed 2 rows in the database\n";

$result = mysqli_query($mysqli, "SELECT @@autocommit");
$row = mysqli_fetch_row($result);
printf("Autocommit is %s\n", $row[0]);

/* 尝试插入更多值 */
$language_code = 'PL';
$native_speakers = 30_555_444;
mysqli_stmt_execute($stmt);
$language_code = 'DK';
$native_speakers = 5_222_444;
mysqli_stmt_execute($stmt);

/* 设置 autocommit=true 将触发提交 */
mysqli_autocommit($mysqli, true);

print
"Committed 2 row in the database\n";
} catch (
mysqli_sql_exception $exception) {
mysqli_rollback($mysqli);

throw
$exception;
}

上述示例将输出

Autocommit is 0
Committed 2 rows in the database
Autocommit is 0
Committed 2 row in the database
Autocommit is 0
Committed 2 rows in the database
Autocommit is 0
Committed 2 row in the database

注意

注意:

此函数不适用于非事务型表类型(如 MyISAM 或 ISAM)。

另请参阅

添加注释

用户贡献的注释 4 notes

jcwebb at dicoe dot com
16 年前
为了清楚起见,autocommit 不仅打开/关闭事务,而且还会“提交”任何等待的查询。
<?php
mysqli_autocommit
($link, FALSE); // 关闭自动
-一些查询 1;
-
一些查询 2;
mysqli_commit($link); // 处理到目前为止的所有查询
-一些查询 3;
-
一些查询 4;
mysqli_autocommit($link, TRUE); // 打开自动
?>
所有 4 个查询都将被处理。
Geoffrey Thubron
17 年前
值得注意的是,您可以使用标准 SQL 执行事务,而无需禁用自动提交。 "START TRANSACTION;" 将启动一个事务。 "COMMIT;" 将提交结果,而 "ROLLBACK;" 将恢复到事务前状态。

CREATE TABLE 和 CREATE DATABASE(以及可能的其他命令)始终立即提交,您的事务似乎已终止。 因此,任何前后命令都将提交,即使随后尝试回滚。

如果您在事务过程中调用 mysqli_close(),则似乎您获得了隐式回滚的功能。

我无法重现下面概述的“代码错误导致锁定”问题(我始终获得成功回滚,并且脚本将多次成功运行)。 因此,我建议该问题已在 php-5.2.2 中修复。
Glen
17 年前
我发现,如果 PHP 由于代码错误在事务过程中退出,则 InnoDB 表可能会一直锁定,直到 Apache 重启。

简单的测试是通过设置 $mysqli_obj->autocommit(false) 并执行插入语句来启动事务。 在到达 $mysqli_obj->commit 语句之前 - 让运行时代码错误炸毁 PHP。 您检查数据库,没有发生插入(您假设发生了回滚).. 然后您去修复错误,并再次尝试... 但这次脚本大约花了 50 秒超时 - 插入语句返回“1205 - 锁定等待超时;尝试重新启动事务”。 没有发生回滚。 而且此错误不会消失,直到您重启 Apache - 无论出于何种原因,资源都不会在进程被杀死之前释放。

我发现,"exit" 而不是 PHP 代码错误不会导致问题。 因此,有一个自动回滚机制 - 它在 PHP 意外死亡时只是惨败。 必须重启 apache 来克服代码错误,这是一个相当极端的措施。

为了避免此问题,我在启动事务时使用 "register_shutdown_function()",并设置一个标志来指示事务正在进行中(因为没有 unregister_shutdown_function())。 请参见下文。 因此,__shutdown_check() 例程(我认为它需要是公共的)在脚本炸毁时被调用 - 它能够调用 rollback()。

这些只是相关的部分,让您了解一下...

<?php

public function begin_transaction() {
$ret = $this->mysqli_obj->autocommit(false);
$this->transaction_in_progress = true;
register_shutdown_function(array($this, "__shutdown_check"));
}

public function
__shutdown_check() {
if (
$this->transaction_in_progress) {
$this->rollback();
}
}

public function
commit() {
$ret = $this->mysqli_obj->commit();
$this->transaction_in_progress = false;
}

public function
rollback() {
$ret = $this->mysqli_obj->rollback();
$this->transaction_in_progress = false;
}
?>

适用于 PHP 5.1.6 + MySQL 5.0.24a。
will at phpfever dot com
18 年前
如果您使用的是 mysql 命令行工具,以下是一些有关 autocommit 功能的提示

1. 要查看当前 autocommit 设置,可以使用以下查询:select @@autocommit; 它将以 1 或 0(开或关)的形式返回当前设置

2. 您可以在 my.cnf 或 my.ini 中管理默认 autocommit 功能,方法是在其中添加以下行:init_connect='set autocommit=0'。 我很确定这不在文档中,但它确实有效。

截至 MySQL 5.1dev,以下是支持事务的当前引擎

InnoDB
BerkeleyDB
Falcon

Falcon 非常新,因此请注意在生产系统上使用它。
To Top