【问题标题】:Run insert outside of TRANSACTION block MySQL在事务块 MySQL 之外运行插入
【发布时间】:2019-03-13 12:28:11
【问题描述】:

是否可以在MySQL TRANSACTION 之外运行MySQL INSERT 命令?

我需要这个,因为我正在记录数据库中的所有错误,即使其他 MySQL 查询在发生错误时应回滚,错误仍应插入到数据库中。

这是一个代码示例:

<?php

DB('main')->query("START TRANSACTION;");
$error = false;
for ($i=0; $i<10; $i++) {
   $rand = rand(0, 10);
   if ($rand < 5) {
       $error = true;
       DB('main')->query("INSERT INTO Errors SET ErrorText = 'There was an error'");
       break;
   }
   DB('main')->query("INSERT INTO RandomTable SET RandomValue = '" . $rand . "'");
}

if ($error) {
    DB('main')->query("ROLLBACK");
} else {
    DB('main')->query("COMMIT");
}

使用此代码,如果发生错误,Errors 表中的行将根本不会插入。如果我不使用TRANSACTIONS,我必须手动删除在错误发生之前插入的所有行。

我知道,我可以简单地将错误的 INSERT 放在 ROLLBACK 命令之后,但是想象一下,有 50 个可能发生错误的地方,每个错误都不同。

【问题讨论】:

  • 简短回答,当然可以。没有什么会迫使您首先使用事务。如果您可以提供一些代码或其他上下文,您的问题可能会更清楚。
  • @Dave 添加了一个代码示例。
  • 最简单的方法大概是将错误日志存储在不受事务影响的MyISAM表中。
  • @DagSondreHansen 我不知道这一点,但我会测试它,如果它真的这样工作,那将完全满足我的需求!
  • 关于在事务中使用 MyISAM 表的建议:不建议这样做,可能会导致复制期间出现奇怪的行为。对于标准 MySQL 复制,这将导致 MyISAM 条目最终出现在二进制日志中 InnoDB 事务之前。对于 Galera 复制,当在混合事务期间发生回滚时,这甚至会破坏整个集群。

标签: php mysql mariadb


【解决方案1】:

计划 C:使用第二个 MySQL 连接来记录错误。

在这方面,使用autocommit=ON 而不使用BEGIN..COMMIT。这样,“日志”记录将被及时插入。

【讨论】:

  • 这是个好主意!可能是迄今为止最好的!谢谢!
【解决方案2】:

如何将错误压入堆栈并稍后保存?

DB('main')->query("START TRANSACTION;");
$error = false;
$errors = [];
for ($i=0; $i<10; $i++) {
   $rand = rand(0, 10);
   if ($rand < 5) {
       $error = true;
       $errors[] = "There was an error with ".$rand;

       break;
   }
   DB('main')->query("INSERT INTO RandomTable SET RandomValue = '" . $rand . "'");
}

if ($error) {
    DB('main')->query("ROLLBACK");
    DB('main')->query("INSERT INTO Errors (ErrorText) values  (...)", $errors );
} else {
    DB('main')->query("COMMIT");
}

【讨论】:

    猜你喜欢
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    相关资源
    最近更新 更多