3

我花了一周的时间试图让事务为我的 MySQL 数据库工作。仍然没有成功。运行Windows 7 x64MySQL Server 5.6.7-rcMySQL .NET Connector 6.6.4

MySQL 声称它TransactionScope是受支持的(我现在已经阅读了整个 Internet),所以我猜我需要一些特殊的配置才能让它工作。这是我到目前为止所尝试的:

自动提交=0

  • my.iniautocommit=0在该部分下方添加[mysqld]
  • my.iniinit_connect='SET autocommit=0'在该部分下方添加[mysqld]
  • 在 Service Manager 中,我已将其添加--autocommit=0为命令行参数。
  • 我已经验证SELECT @@autocommit返回 0。

sql_mode=传统

  • my.inisql-mode="TRADITIONAL"在该部分下方添加[mysqld]
  • 在 Service Manager 中,我已将其添加--sql-mode=TRADITIONAL为命令行参数。

分布式事务协调器

  • 我试过启用/禁用 DTC 服务。

下面的示例在调用时立即引发异常(System.Transactions.TransactionException必须通过 Ctr+Alt+E 启用异常)Open()。错误消息是操作对于事务的状态无效。. 显然,服务器对事务的东西不满意——这可以通过没有发生回滚的事实来证明。

var factory = System.Data.Common.DbProviderFactories.GetFactory("MySql.Data.MySqlClient");

using (var transaction = new System.Transactions.TransactionScope())
{
    var connection = factory.CreateConnection();
    connection.ConnectionString = "Server=localhost;Port=3306;Database=test;User ID=user;Password=user";
    connection.Open(); // <-- silent TransactionException here!

    var command = connection.CreateCommand();
    command.CommandText = "CREATE TABLE TestTable (ID INT) ENGINE = InnoDB DEFAULT CHARSET=utf8;";

    command.ExecuteNonQuery();

    command.CommandText = "INSERT INTO TestTable (ID) VALUES (123);";
    command.ExecuteNonQuery();

    // ATTENTION! This should imply a rollback!
    // transaction.Complete();
}

示例代码适用,SQL Server所以我确定这个问题与MySQL.

问:我什么都试过了。我需要做什么才能使此TransactionScope代码起作用MySQL

4

1 回答 1

0

MySQL 将在执行 DDL 语句时自动提交活动事务(请参阅http://dev.mysql.com/doc/refman/5.5/en/cannot-roll-back.html)。因此 CREATE TABLE 之后的任何内容都不会成为事务的一部分。

如果您按如下方式执行 SQL 语句,也会发生同样的事情:

START TRANSACTION;
CREATE TABLE TestTable (ID INT) ENGINE = InnoDB DEFAULT CHARSET=utf8;
INSERT INTO TestTable (ID) VALUES (123);
ROLLBACK;

尝试将您的代码更改为:

var factory = MySqlClientFactory.Instance;
string connectionString = "Server=localhost;Port=3306;Database=test;User ID=user;Password=user";

// DDL cannot be performed in transaction as will commit
using (var connection = factory.CreateConnection())
{
    connection.ConnectionString = connectionString;
    connection.Open();

    var command = connection.CreateCommand();
    command.CommandText = "CREATE TABLE TestTable (ID INT) ENGINE = InnoDB DEFAULT CHARSET=utf8;";
    command.ExecuteNonQuery(); // will always commit here
}

// DML can be performed in transaction
using (var transaction = new System.Transactions.TransactionScope())
using (var connection = factory.CreateConnection())
{
    connection.ConnectionString = connectionString;
    connection.Open();   

    var command = connection.CreateCommand();
    command.CommandText = "INSERT INTO TestTable (ID) VALUES (123);";
    command.ExecuteNonQuery();

    // should rollback here
    //transaction.Complete();
}
于 2013-04-03T08:01:36.583 回答