【问题标题】:Commit instead of rollback?提交而不是回滚?
【发布时间】:2021-12-10 10:55:55
【问题描述】:

简单示例(伪代码):

for (int i = 0; i < 100; i++) {
    START TRANSACTION;  
    SELECT id, name FROM employees WHERE id = i;

  
    IF (someFunction(id)) {
        ROLLBACK;
        CONTINUE; // GO TO NEXT EXECUTION OF FOR LOOP
    }

    UPDATE company SET good = good + 1;

    COMMIT;
}

我可以在这个示例中使用 COMMIT(所以我的脚本中将有两个 COMMIT)而不是 ROLLBACK 吗?

如果我在选择后使用 COMMIT 而不是 ROLLBACK 对数据库有什么影响吗?

这里的 MySQL 和 PostgreSQL 有什么区别吗?

【问题讨论】:

  • someFunction 是否使用数据库?
  • @ysth 不,someFunction 不使用数据库。
  • 所以对于每个 id 你开始一个新的事务,所以 cmit 什么都不做,就像你的 cqase 中的回滚一样,因为它只有 1 个命令
  • 您的伪代码毫无意义。根据您在此处发布的内容,我希望执行 someFunction(id) 作为 UPDATE 查询的一部分所做的任何事情,并完全取消整个 START TRANSACTION | COMMIT | ROLLBACK 事情。
  • 只需省略 COMMITROLLBACK 并在代码完成后提交事务。

标签: mysql sql postgresql


【解决方案1】:

Select 本身既不需要回滚也不需要提交。只有在 DML(插入、更新、删除)之后才需要这些。此外,通常认为在事务中只有 1 次提交会更好。整个交易的想法完全成功或完全作为一个单元。所以你的伪代码变成:

START TRANSACTION;   
for (int i = 0; i < 100; i++) {
    SELECT id, name FROM employees WHERE id = i;

    IF NOT (someFunction(id)) {
       UPDATE company SET good = good + 1;  
    }
}
COMMIT;

【讨论】:

  • 最好是SELECT id, name FROM employees WHERE ( id &gt;= 0 AND id &lt; 100 ),然后遍历每个获取的行。这将避免多次SELECT 调用,这比简单地从已经执行的查询中获取结果更昂贵。
  • 这并不完全正确。在 Postgres 中,如果自动提交被禁用,则 SELECT 启动一个事务,并且要结束该事务,您需要提交或回滚,否则连接保持状态“事务中的空闲”。在 MySQL 中,当自动提交被禁用时,如果默认的 REPEATABLE READ 隔离有效,则可能还需要结束由 SELECT 启动的事务以查看其他事务所做的更改。
  • @a_horse_with_no_name 在我的示例中,如果示例将在两个数据库上运行并且我使用提交或回滚无关紧要,我是否必须使用提交或回滚?请添加新答案。
【解决方案2】:

这是@Belayer 答案的变体,我在其中做了以下更改:

  1. 执行单个SELECT,以减少查询次数
  2. 在最终使用单个 UPDATE 递增之前,保持company.good 应递增的运行总次数。
new_good = 0;
SELECT id, name FROM employees WHERE id >= 0 AND i < 100
for each fetched row {
    IF NOT (someFunction(id)) {
       new_good++;
    }
}
START TRANSACTION /* Probably not needed */
UPDATE company SET good = good + new_good;  
COMMIT /* Probably not needed */;

这可能完全消除了对事务的需要,因为任何对 SELECT 或 fetch 的失败调用都不会导致对 new_good 的更改,因此当它最终到达 UPDATE 时,new_good 仍将包含一个有效值(即使是 0)。

【讨论】:

    【解决方案3】:

    因此,我理解您的问题是询问 ROLLBACK 或 COMMIT 是否更好,仅在选择之后,您确定不会在此事务中进行任何更改。

    就mysql而言,没有理由进行回滚或提交;由于没有进行任何更改,因此也没有做任何事情,并且不做任何事情都不会导致任何问题。但目前尚不清楚您希望首先通过在事务中进行选择来完成什么,或者为循环的每次迭代设置一个单独的事务。如果您提供更多信息,您会得到更好的建议。

    【讨论】:

      猜你喜欢
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-14
      • 2020-04-13
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      相关资源
      最近更新 更多