关于逻辑/算法的想法以及如何防止对SqlServer的线程写入中的竞争

我有以下逻辑:

public void InQueueTable(DataTable Table) { int incomingRows = Table.Rows.Count; if (incomingRows >= RowsThreshold) { // asyncWriteRows(Table) return; } if ((RowsInMemory + incomingRows) >= RowsThreshold) { // copy and clear internal table // asyncWriteRows(copyTable) } internalTable.Merge(Table); } 

这个算法有一个问题:

  • 给定RowsThreshold = 10000

  • 如果incomingRowsRowsInMemory放在RowsThreshold :(1)异步写出数据,(2)合并传入数据

  • 如果incomingRows超过RowsThreshold ,则异步写入传入数据

但是如果??? 假设第二个线程旋转并调用asyncWriteRows(xxxTable); 另外,拥有异步方法的每个线程都将写入SqlServer中的同一个表: SqlServer是否将这种multithreading写入function处理到同一个表中?

跟进
根据Greg D的建议:

 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString, sqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction)) { // perform bulkcopy } 

无论如何,我仍然有发信号通知asyncWriteRows(copyTable)的问题。 该算法需要确定是否需要继续复制internalTable,clear internalTable和asyncWriteRows(copyTable)。 我认为我需要做的是将internalTable.Copy()调用移动到它自己的方法:

 private DataTable CopyTable (DataTable srcTable) { lock (key) { return srcTable.Copy(); } } 

…然后对InQueue方法进行以下更改:

 public void InQueueTable(DataTable Table) { int incomingRows = Table.Rows.Count; if (incomingRows >= RowsThreshold) { // asyncWriteRows(Table) return; } if ((RowsInMemory + incomingRows) >= RowsThreshold) { // copy and clear internal table // asyncWriteRows(CopyTable(Table)) } internalTable.Merge(Table); } 

…最后,添加一个回调方法:

 private void WriteCallback(Object iaSyncResult) { int rowCount = (int)iaSyncResult.AsyncState; if (RowsInMemory >= rowCount) { asyncWriteRows(CopyTable(internalTable)); } } 

这就是我所确定的解决方案。 任何反馈?

有什么理由不能使用交易吗?

我现在承认我不是这个领域的专家。

使用事务和游标,如果操作很大,您将获得锁定升级。 例如,您的操作将开始锁定一行,然后是一个页面,然后是表格,如果需要,则阻止其他操作运行。 我认为SQL Server只是将这些被阻止的操作排队等待锁定被释放的白痴,但它只是返回错误而且由API程序员继续重试(如果我错了,有人会纠正我,或者如果它在更高版本中修复)。 如果您很乐意阅读可能会复制的旧数据,就像我们一样,我们更改了隔离模式以不必要地停止服务器阻塞操作。 ALTER DATABASE [dbname] SET READ_COMMITTED_SNAPSHOT ON;

您也可以更改插入语句以使用NOLOCK。 但请仔细阅读。