运行多个线程时 SQL 事务发生内部连接致命错误
Posted
技术标签:
【中文标题】运行多个线程时 SQL 事务发生内部连接致命错误【英文标题】:Internal connection fatal error on SQL Transaction when running multiple threads 【发布时间】:2021-10-19 02:12:30 【问题描述】:我正在编写一个应用程序,它同时对某些设备进行多项测试。 测试后我想将结果添加到数据库中。 我在数据库中有 3 个表:Testsequence、Maintest、Subtest 要链接数据,我必须知道“父”表对象的 id
但是当我运行超过 1 个任务时,我得到:"Internal connection fatal error." on
sequenceId = Convert.ToInt32(sqlcommand.ExecuteScalar());
目前我正在使用带有 Microsoft SQL Server 的本地数据库(使用 System.Data.SqlClient;)
public static void AddResults(Device device)
using (var connection = new SqlConnection(Settings.DBConnectionString))
SqlTransaction transaction;
transaction = _sqlConnection.BeginTransaction(IsolationLevel.ReadCommitted);
try
SqlCommand sqlcommand = _sqlConnection.CreateCommand();
sqlcommand.Connection = _sqlConnection;
sqlcommand.Transaction = transaction;
// Add Testsequence
sqlcommand = new SqlCommand(@"INSERT INTO TestSequence (IdMachine,DateTime) VALUES (@IdDevice,@DateTime) SELECT SCOPE_IDENTITY()", _sqlConnection, transaction);
sqlcommand.Parameters.Add(new SqlParameter("@IdDevice", device.DataBaseId));
sqlcommand.Parameters.Add(new SqlParameter("@DateTime", device.Progress.ResultActive.Time));
sequenceId = Convert.ToInt32(sqlcommand.ExecuteScalar());
foreach (TestCategory category in device.Progress.ResultActive)
foreach (MainTest mainTest in category)
// Add MainTest
if (mainTest.Time == null) continue;
sqlcommand = new SqlCommand(@"INSERT INTO MainTests (IdSequenceMT,IdTestNameMT,DateTimeMT,Passed) VALUES @IdSequenceMT,@IdTestNameMT,@DateTimeMT,@Passed) SELECT SCOPE_IDENTITY()", _sqlConnection, transaction);
sqlcommand.Parameters.Add(new SqlParameter("@IdSequenceMT", sequenceId));
sqlcommand.Parameters.Add(new SqlParameter("@IdTestNameMT", mainTest.Id));
sqlcommand.Parameters.Add(new SqlParameter("@DateTimeMT", mainTest.Time));
sqlcommand.Parameters.Add(new SqlParameter("@Passed", mainTest.Pass));
mainTestId = Convert.ToInt32(sqlcommand.ExecuteScalar());
foreach (SubTest subTest in mainTest)
// Add SubTest
if (subTest.Pass == null) continue;
sqlcommand = new SqlCommand(@"INSERT INTO SubTests
(IdMainTestST,IdTestName,DateTimeST,Passed,Log_enUS,Log_deDE) VALUES (@IdMainTestST,@IdTestName,@DateTimeST,@Passed,@Log_enUS,@Log_deDE)",
_sqlConnection, transaction);
sqlcommand.Parameters.Add(new SqlParameter("@IdMainTestST", mainTestId));
sqlcommand.Parameters.Add(new SqlParameter("@IdTestName", subTest.Id));
sqlcommand.Parameters.Add(new SqlParameter("@DateTimeST", subTest.Time));
sqlcommand.Parameters.Add(new SqlParameter("@Passed", subTest.Pass));
sqlcommand.Parameters.Add(new SqlParameter("@Log_enUS", subTest.Log));
sqlcommand.Parameters.Add(new SqlParameter("@Log_deDE", subTest.Log));
sqlcommand.ExecuteNonQuery();
if (connection.State != System.Data.ConnectionState.Open) connection.Open();
transaction.Commit();
log.Info($"SQL device.Serialnumber|device.DataBaseId: Testsequence Id: sequenceId added");
catch (Exception e)
transaction.Rollback();
log.Info($"SQL : device.Serialnumber Testsequence add: transaction rollback\ne");
Helper.UiMessage($"device.Serialnumber Project.Properties.Resources.results_not_added", 60);
我尝试了什么:
在我有一个用于连接的全局变量之前......这不是问题 我没有使用 using 语句...无论如何这也不是问题也许你看到我的代码不是最好的 :D 如果你有任何其他改进的想法,也请写评论。
我也不知道问题出在多线程、查询命令还是事务中多个命令的执行。
提前致谢:)
【问题讨论】:
请标记您的 DBMS 据我了解,事务是将“更多查询”放在一批中以传输到服务器 => 我想保持网络流量尽可能低。如果我只能使用单个命令,我该如何重写我的代码......以及为什么它在使用单个设备执行时可以工作?我还需要在下一个命令中使用的父级 => Scope_identity 的 id... 您仍在使用您的全局_sqlConnection
创建事务并执行命令。将其切换到局部变量connection
。 transaction
也应该在 using
中。另见***.com/questions/17552829/…
try
之后的前三行似乎毫无意义,因为sqlCommand
已被覆盖。事务不会降低网络流量,它们确保以原子方式生成一组语句。为了尽量减少流量,更重要的是让它表现得更好,您可以使用表值参数进行批量插入
【参考方案1】:
...问题就在屏幕前...-.-
旧的 _sqlConnection 是之前“版本”的遗留物。
将 _sqlConnection 更改为连接 添加了缺少的交易使用语句感谢@Charlieface
【讨论】:
以上是关于运行多个线程时 SQL 事务发生内部连接致命错误的主要内容,如果未能解决你的问题,请参考以下文章
SQL SERVER中,多个事物间同是并发操作数据时,会发生事务之间数据读取不一致的 情况,