在我的网络应用程序中,用户可以一次插入大量数据,以提高性能,我正在使用 SqlBulkCopy
类。对于插入两个不同表的单个操作,它会运行多次。如果用户取消操作或操作失败,那么我需要回滚数据,因此我使用隔离级别快照将所有内容包装在一个事务中。
据我了解,使用快照隔离将允许其他用户同时写入/读取表。然而,当一个数据上传发生时,它会阻止任何其他对表的写入,直到整个父事务完成。
这里是一些显示问题的简化代码。我排除了很多功能,但想法保持不变。我迭代了一些内存中的集合,将它们批量复制到一个表,检索它们,然后批量复制到另一个表。
using (var transaction = myDbContext.Database.BeginTransaction(
System.Data.IsolationLevel.Snapshot))
{
var myCollectionOfObjects;
while(!GetData(ref myCollectionOfObjects))
{
SqlBulkCopy bulkCopy = new SqlBulkCopy(myCon, transaction);
//Sets the columns + rows
SetUp(bulkCopy);
bulkCopy.WriteToServer();
//After the bulkcopy operation is complete
// we retrieve the rows inserted and do another bulk copy to a different table
var recentlyAddedRows = GetRecentlyAddedRow();
SqlBulkCopy otherTableBulkCopy = new SqlBulkCopy(myCon, transaction);
SetUpBulkCopyForOtherTable(otherTableBulkCopy);
otherTableBulkCopy.WriteToServer();
}
transaction.Commit();
}
因此,如果一个用户当前在该事务中,即使它正在回滚,所有其他写入该表的事务都将被阻止,因此其他执行相同功能或试图写入该表的用户将被阻止。
这是预期的行为吗?有没有办法解决这个问题?
编辑
通过查看在 SQL 中应用的锁,这似乎是由于 bulkcopy 类导致在表对象上设置排他锁 (X),就像您一次插入一个一样,只有一个对表应用意向锁 (IX)。仍然不确定是否有办法解决这个问题,但我认为这是由于锁定升级造成的。
在我的一些测试中,更改表索引上的允许页面锁定和更改批量复制的批处理大小已经绕过完全锁定,但它们是喜怒无常的。
最佳答案
IsolationLevel
仅指读取而不是写入。如果您的一个客户端正在写入数据,那么另一个客户端应该能够读取事务开始前的数据,但是,它不能同时写入。
关于c# - SqlBulkCopy 在事务内部插入时阻止任何其他对表的写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34227800/