首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在mysqli中开始和结束事务?

如何在mysqli中开始和结束事务?
EN

Stack Overflow用户
提问于 2012-08-23 20:48:56
回答 5查看 58.6K关注 0票数 44

据我所知,事务在调用$mysqli->autocommit(FALSE);语句后开始,在调用$mysqli->commit();命令后结束,如下例所示。

代码语言:javascript
运行
复制
<?php
//Start transaction 
$mysqli->autocommit(FALSE);
$mysqli->query('UPDATE `table` SET `col`=2');
$mysqli->query('UPDATE `table1` SET `col1`=3;');
$mysqli->commit();
//End transaction

//Executing other queries without transaction control
$mysqli->query("Select * from table1");
$mysqli->query("Update table1 set col1=2");
//End of executing other queries without transaction control

//Start transaction 
$mysqli->autocommit(FALSE);
$mysqli->query('UPDATE `table` SET `col`=2');
$mysqli->query('UPDATE `table1` SET `col1`=3;');
$mysqli->commit();
//End transaction
?>

我没理解错吧?如果没有,请纠正我,因为这实际上是我第一次在现实生活中使用交易。

谢谢。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-08-23 20:59:13

Update Novembre 2020@Dharman给出了一个更好的答案,提供了更多关于mysqli事务的详细信息,只需检查一下:https://stackoverflow.com/a/63764001/569101

根据the php doc的说法,你是对的。

代码语言:javascript
运行
复制
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE Language LIKE CountryLanguage");

/* set autocommit to off */
$mysqli->autocommit(FALSE);

/* Insert some values */
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");

/* commit transaction */
$mysqli->commit();

/* drop table */
$mysqli->query("DROP TABLE Language");

/* close connection */
$mysqli->close();
?>

在上面的示例中:

由于autocommit(FALSE).

  • the DROP TABLE是自动提交的,因为autocommit(FALSE)已被->commit();.

重置,因此

  • CREATE TABLE是自动提交的,因为它不是默认的behaviour.
  • the INSERT INTO 自动提交
票数 35
EN

Stack Overflow用户

发布于 2013-05-24 17:02:01

j0k基本上是正确的,除了在drop表中。

未使用->commit()打开自动提交

相反,DROP TABLE是一个DDL查询,并且DDL查询始终是隐式提交的,并且将提交您以前未提交的所有工作。

因此,如果您没有提交工作,DDL查询将强制执行此提交。

票数 33
EN

Stack Overflow用户

发布于 2020-09-06 20:09:35

如何在mysqli中使用事务?

先决条件

为了使事务正常运行,您应该启用异常错误报告。否则,mysqli将不会报告错误,事务将无法正确执行。或者,您可以手动检查每个查询,但不建议这样做。要正确连接mysqli,请使用以下3行代码:

代码语言:javascript
运行
复制
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');
$mysqli->set_charset('utf8mb4'); // always set the charset

事务只适用于事务性表。确保您的表存储引擎支持事务。例如,MyISAM会忽略提交/回滚。

交易记录

使用mysqli创建事务有两种可能的方法。默认情况下,所有查询/语句在执行后都会立即提交。您可以关闭自动提交,也可以使用一次性事务。

在以下情况下,事务将提交到数据库:

在调用commit

  • after setting autocommit=1

  • when启动另一个transaction

使用自动提交(False)

如果关闭自动提交,您将决定何时提交,但调用commit()不会重新打开自动提交。

代码语言:javascript
运行
复制
//Start transaction
$mysqli->autocommit(false);

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->commit();
// Changes are committed, but autocommit is not switched back on

// Following queries are still transactional.
// They will not be committed unless you call commit or switch autocommit back on
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');

$directorId = $mysqli->insert_id;
$movieTitle = 'Titanic';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->autocommit(true);
// All queries are committed and everything that follows will be immediately committed.

使用begin_transaction()

您可以使用begin_transaction()启动一次性事务。这不会设置autocommit=false,因此当您调用commit()时,您将结束事务而不启动新事务。

代码语言:javascript
运行
复制
//Start transaction 
$mysqli->begin_transaction();

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

$mysqli->commit();
// Changes are committed and the transaction has ended

// Following queries will be committed one by one as soon as they are peformed.
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');

$directorId = $mysqli->insert_id;
$movieTitle = 'Titanic';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

执行DDL语句

有些SQL语句会触发显式提交,但不会影响autocommit的值。

代码语言:javascript
运行
复制
//Start transaction 
$mysqli->autocommit(false);

$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');

$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();

// The following will call commit but it will not set autocommit=true
$mysqli->query('TRUNCATE TABLE movie_genre');
// if you want to switch autocommit back on, you have to call: 
$mysqli->autocommit(true);

回滚

如果发生异常,那么PHP将结束脚本的执行,并且代码永远不会到达commit语句。但是,在某些情况下,您可能希望显式地回滚事务,例如,为了避免在代码中的其他位置意外调用commit。

下面是这样一个事务的示例。第二个查询试图插入到一个不存在的表中,这意味着mysqli将抛出异常。我们捕获异常并回滚事务,而不是让PHP脚本死掉。值4永远不会插入到数据库中,因为两个查询都已回滚。

代码语言:javascript
运行
复制
try {
    // Start transaction
    $mysqli->begin_transaction();

    $mysqli->query('INSERT INTO some_table(col2) VALUE(4)');
    $mysqli->query('INSERT INTO does_not_exist(col2) VALUE(4)');

    // Commit changes
    $mysqli->commit();
} catch (\Throwable $e) {
    // Something went wrong. Rollback
    $mysqli->rollback();
    // Rethrow the exception so that PHP does not continue
    // with the execution and the error can be logged in the error_log
    throw $e;
}
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12091971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档