我如何原子地替换一组行?

时间:2013-09-08 14:50:26

标签: sql-server-2008 transactions

我有一个从文件中填充的产品表。当文件更新时,我需要用新数据替换表中的所有行。

执行此操作的简单方法是删除所有现有行,然后插入新行。但是我担心如果一个事务在插入的同时读取行,那么事务可能会从两个集合中读取行。

那么我该怎么做呢?如果我使用SERIALIZABLE事务,那么我认为在这种情况下可能存在死锁。

2 个答案:

答案 0 :(得分:1)

只有当两个事务每个至少使用两个资源(表/行)时,才会出现死锁。这是你的交易中的情况吗?从表中删除所有行也是低效的。您可能必须检查是否可以使用TRUNCATE语句及其对事务的影响。

@IanWarburton,因为@steve建议你不要使用TRUNCATE语句而不是坚持使用DELETE语句!这是一个可能适合您的解决方案。 RDBMS通常有一些处理死锁的方法。在SQL Server中,可以为会话设置死锁优先级。想法是为会话设置高优先级(主txn),删除现有行并通过读取您提到的文件插入新行。对于所有其他会话事务(其他txns),设置低优先级,以便在发生死锁时这些事务将成为受害者。这使得主txn执行完成。您需要为主txn使用SERIALIZABLE隔离级别。其他txns在死锁时收到错误(1205),因此回滚它们的事务并重新启动它们。

有关死锁检测和处理的更多信息,请参阅http://technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx

答案 1 :(得分:0)

这个怎么样......

using (var transaction = new TransactionScope())
{
   Context.Database.ExecuteSqlCommand("DELETE Items WITH (TABLOCKX)");

   SqlBulkCopyHelper.BulkInsert(Context.Database.Connection.ConnectionString, "Items", items);
}

其中'Context'是我从here获得的实体框架DbContext和SqlBulkCopyHelper。

TransactionScope默认为SERIALIZABLE,所以我认为表锁定将持续一段时间。