【问题标题】:Why does SQL Transaction does not Rollback after connection is lost - C#?为什么连接丢失后 SQL 事务不回滚 - C#?
【发布时间】:2020-03-21 21:43:47
【问题描述】:

我正在使用 MariaDB 10.3.21,我想知道为什么在连接丢失后没有从 SQL-Server 完成回滚。

我正在使用下面的代码更新几个表。为了检查在连接丢失后是否还从服务器端进行回滚,我在 objTransaction.Commit() 命令中设置了一个断点,在点击它之后,我中断了网络连接。

不幸的是,字段的更新在没有提交命令的情况下被接管。我假设如果连接丢失,服务器将执行隐式回滚。

有什么想法吗?非常感谢!

    public void ExecuteSQL(List<string> pQueryList)
    {
        using (MySqlConnection objConnection = new MySqlConnection(ConnectionString))
        {
            try
            {
                objConnection.Open();

                MySqlCommand objCommand = objConnection.CreateCommand();
                MySqlTransaction objTransaction;

                // Start Transaction
                objTransaction = objConnection.BeginTransaction();

                // Must assign both transaction object and connection
                // to Command object for a pending local transaction
                objCommand.Connection = objConnection;
                objCommand.Transaction = objTransaction;

                try
                {
                    // Set autocommit = off the this session
                    //objCommand.CommandText = "SET autocommit = 0";
                    objCommand.ExecuteNonQuery();

                    foreach (string query in pQueryList)
                    {
                        // Execute the SQL Queries
                        objCommand.CommandText = query;

                        if (objCommand.ExecuteNonQuery() <= 0)
                        {
                            throw (new Exception("Fehler bei ExecuteNonQuery. Anzahl der betroffenen Zeilen fehlerhaft."));
                        }
                    }

                    // Commit Transaction
                    objTransaction.Commit();
                }
                catch (Exception)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        // Rollback 3x versuchen (falls Netzwerkverbindung abgebrochen ist)
                        try
                        {
                            objTransaction.Rollback();
                            break;
                        }
                        catch (Exception)
                        {
                            Thread.Sleep(100);
                        }
                    }                        
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Das speichern in die Datenbank ist fehlgeschlagen!\n\n" + ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }

【问题讨论】:

    标签: transactions mariadb rollback


    【解决方案1】:

    我认为您需要关闭“自动提交”功能,默认启用。

    什么是自动提交?

    在每个 SQL 语句之后导致提交操作的设置。不建议将此模式用于处理跨多个语句的事务的 InnoDB 表。它可以帮助提高 InnoDB 表上的只读事务的性能,从而最大限度地减少锁定和生成 undo 数据的开销,尤其是在 MySQL 5.6.4 及更高版本中。它也适用于处理不适用事务的 MyISAM 表。

    (引自https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_autocommit

    在此处阅读有关自动提交以及如何关闭它的信息: https://dev.mysql.com/doc/refman/5.6/en/commit.html

    【讨论】:

    • 正如你在我的代码中看到的,我已经检查过关闭“自动提交”功能 (objCommand.CommandText = "SET autocommit = 0";),但这也不起作用。
    • @Marco 如何先在 DBeaver 等 SQL 编辑器中手动检查它,尝试一些不同的语法(我可以在这里看到:mariadb.com/kb/en/… 有多个),例如:SET SESSION autocommit: = 0;
    • 我可以解决这个问题。存储引擎设置为不支持事务的 MyISAM。我将其更改为 InnoDB 并且可以正常工作。 (link。感谢psychoboi111 提供有关SQL 编辑器的提示。HeidiSQL 为我提供了有关引擎的正确提示!
    • @Marco och,我想过提到存储引擎,但后来我认为 MariaDB 的默认设置是 InnoDB。无论如何,没问题:)
    猜你喜欢
    • 2013-10-07
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 2015-02-11
    相关资源
    最近更新 更多