我正在创建一个程序,它将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();
}
但我觉得效率不高。这是正确的解决方案吗?或者有更好的解决方案,请给我一个示例代码。
答案 0 :(得分:1)
目前尚不清楚是什么导致了僵局。 (请注意,涉及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的PRIMARY KEY为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