【问题标题】:What happens if there is a power outage before calling commit or rollback?如果在调用 commit 或 rollback 之前断电会发生什么?
【发布时间】:2014-09-09 03:19:09
【问题描述】:

所以我一直在用这段代码进行测试:

MySqlTransaction trans = null;
                    var con = new MySqlConnection(DBInfo.CON_STRING);
                    try
                    {

                            con.Open();
                            trans = con.BeginTransaction();

                            var query = "INSERT INTO test (num) VALUE (@val1)";
                            var cmd = new MySqlCommand(query, con);
                            cmd.Transaction = trans;
                            cmd.Prepare();

                            cmd.Parameters.AddWithValue("@val1", 0);

                            for (int i = 0; i <= 15; i++)
                            {

                                    cmd.Parameters["@val1"].Value = i;
                                    cmd.ExecuteNonQuery();
                                    if (i == 10)
                                    {
                                            //throw new DivideByZeroException();
                                            MessageBox.Show("pause");
                                    }
                            }

                            trans.Commit();
                    }
                    catch (Exception ex)
                    {

                            MessageBox.Show(ex.StackTrace);

                            try
                            {
                                if (trans != null) trans.Rollback();
                            }
                            catch (Exception ex1)
                            {
                                    MessageBox.Show(ex1.Message);
                            }
                    }
                    finally
                    {
                        con.Close();
                    }

提交和回滚方法。我有一个问题。在for 块中,我有一个消息框来暂停代码的执行,这样我就可以停止程序来模拟程序的突然执行。问题是查询没有提交,但是服务器发生了什么?它会自动回滚吗?例如,如果运行程序的 PC 恰好是服务器并且停电,会发生什么情况? (假设停电发生在执行for 块的过程中。

【问题讨论】:

  • FWIW:使用using(如果 MySQL 驱动程序支持,则使用 TransactionScope)。请注意,这个可能的答案取决于 MySQL 事务中涉及的表(InnoDB - 好,MyISAM - 坏)。但是,除非所有这些......当连接终止时,显式启动的事务(请参阅自动提交事务!)未提交的事务会隐式回滚。
  • @user2864740 他支持
  • @IVAAAN123 很高兴知道这一点。我总是“卡”在 SQL Server 上。

标签: c# mysql visual-studio transactions


【解决方案1】:

当数据库服务器在断电后重新启动时,它会恢复到只包含已提交工作的干净状态。

当数据库客户端在事务中途被切断时,服务器会通过回滚自动清理事务。

【讨论】:

    【解决方案2】:

    这是一个非常好的问题。 MySQL 发生的事情是它是ACID compliant。 ACID 合规性的字面用例是“如果我们在交易期间拔掉插头会发生什么”。本质上,它归结为每个操作都是原子的,这意味着它要么完成,要么不完成。如果没有,那么保证保存该事务之前的数据库状态,您可以在那里恢复。如果它完成,那么您可以确保如果您的下一个操作失败,您当前的状态将被保存。

    有趣的事实:NoSQL 数据库 MongoDB 的主要警告之一是它不符合 ACID。因此,如果您有一个更新多个集合的事务并且您拔掉了电源插座,那么您的数据库的状态是不确定的(某些内容可能已保存,而另一些可能尚未保存)。

    如果您有任何问题,请告诉我!

    【讨论】:

      【解决方案3】:

      当您启动事务时,数据库命令实际上并没有更改数据库本身,而是维护用户请求的更改列表。有很多机制可以使这项工作明显透明,但更改存储在日志中。 当您进行提交时,它会将所有这些事务写入一个块 toe 数据库中,因此所有更改都是同时进行的。如果您进行回滚,或者您什么都不做(例如停电的情况),那么事务日志将被删除,就好像您从未执行过这些命令一样。

      什么是在日志中延迟,以及原子承诺(意味着它们都在没有人、没有另一个线程或另一个进程干预的情况下一次性保存)可能会导致一些奇怪的事情。

      例如,如果您有两个到数据库的连接并且您执行以下操作:

      1. 打开两个单独的连接,connection1 和 connection2
      2. 在连接 1 上开始事务
      3. 使用连接 1 将数据行 R 插入到表 T 中
      4. 使用连接 2,查看表 T,您将找不到 R 行
      5. 在 connection1 上提交事务
      6. 现在使用连接 2,查看表 T,您现在将找到 R 行。

      这是绝对正确的行为。第4点的数据还在connection1的事务日志中,还没有写入数据库表,所以在connection 2上是不可见的。只有connection1的事务日志提交到数据库后,在connection 2上才可见。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 2016-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多