c# - 使用并行复制表会导致 MySQL 死锁

标签 c# mysql multithreading parallel-processing deadlock

我正在制作一个程序,将 db1 中的所有表数据合并到 db2 中的一个表中。但它给出了死锁错误。

这是我的代码。

Parallel.ForEach(tableList, table =>
{
    using (MySqlConnection conn = new MySqlConnection(DBconnection))
    {
        using (MySqlCommand cmd = new MySqlCommand(query, conn))
        {
            try
            {
                conn.Open();
                cmd.CommandText = "INSERT INTO db2.targetTable (id, value1, value2) " +
                "SELECT (SELECT id FROM db2.User u WHERE u.id = user LIMIT 1), " +
                "value1, value2 FROM db1." + table;
                cmd.CommandTimeout = 600000;
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
                Console.WriteLine("ERROR : " + ex.Message);
        }
    }
}

我认为子查询导致了问题。

也许如果我添加这段代码,它可以解决问题:

  Object sync = new Object();
  lock (sync)
  {
     cmd.ExecuteNonQuery();
  }

但我认为这效率不高。这是一个正确的解决方案吗?或者有更好的解决方案,请给我一个示例代码。

最佳答案

目前尚不清楚是什么导致了僵局。 (请注意,涉及 MyISAM 表的 SQL 操作会尝试获取整个表的独占锁,因此我假设您使用的是 InnoDB 或 MyISAM 之外的其他存储引擎。)

我会避免 SELECT 列表中的相关子查询,而是使用 JOIN 模式。我相信,通过 SELECT 列表中的子查询,MySQL 将为外部查询中返回的每一行执行该子查询。

INSERT INTO db2.targetTable (id, value1, value2) 
SELECT u.id
     , t.value1
     , t.value2 
  FROM db1.table t
  LEFT
  JOIN db2.User u
    ON u.id = t.user

语句中的子查询包含 LIMIT 1条款。如果需要的话,因为 id db2.User 中的列表不是唯一的(这会很奇怪,但可能),那么我上面给出的查询需要包含 GROUP BY <db1.table1 PRIMARY KEY> ,以避免从源行创建重复行。

如果 db1.table 的主键为 id ,那么:

INSERT INTO db2.targetTable (id, value1, value2) 
SELECT u.id
     , t.value1
     , t.value2 
  FROM db1.table t
  LEFT
  JOIN db2.User u
    ON u.id = t.user
 GROUP BY t.id 

关于c# - 使用并行复制表会导致 MySQL 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21345184/

相关文章:

MySQL - 删除一行并使用正确的排序 ID 对其他行重新排序

java - 如何从多个线程测试一个类的线程安全性?

c - POSIX 线程中的挂起和恢复

c# - Azure 文件挂载到云服务

c# - 使用 MVVM 从 ObservableCollection 中删除 selectedItem

c# - 如何在 WPF 中创建动画消息横幅

mysql - 错误 1129 : Host '' blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

c# - 如何在C#中获取已启动应用程序的PID

php - 将mysql查询数据显示为数组

c++ - 在 C++ 中实现线程的标准做法?