我有一个从文件中填充的产品表。更新文件后,我需要用新数据替换表中的所有行。
执行此操作的简单方法是删除所有现有行,然后插入新行。但是我担心,如果一个事务在插入的同时读取行,那么事务最终可能会从两组读取行。
那么我该如何阻止呢?如果我使用 SERIALIZABLE 事务,那么我认为在这种情况下可能会出现死锁。
我有一个从文件中填充的产品表。更新文件后,我需要用新数据替换表中的所有行。
执行此操作的简单方法是删除所有现有行,然后插入新行。但是我担心,如果一个事务在插入的同时读取行,那么事务最终可能会从两组读取行。
那么我该如何阻止呢?如果我使用 SERIALIZABLE 事务,那么我认为在这种情况下可能会出现死锁。
只有当两个事务各自使用至少两个资源(表/行)时,才会出现死锁。您的交易中是否存在这种情况?从表中删除所有行也是低效的。您可能必须检查是否可以使用 TRUNCATE 语句及其对事务的影响。
@IanWarburton,正如@steve 建议的那样,您不想使用 TRUNCATE 语句,而是坚持使用 DELETE 语句!这是一个可能对您有用的解决方案。RDBMS 通常有一些处理死锁的方法。在 SQL Server 中,可以为会话设置死锁优先级。想法是为会话(main txn)设置高优先级,该会话通过读取您提到的文件删除现有行并插入新行。对于所有其他会话事务(其他 txns),设置低优先级,以便这些事务在死锁的情况下成为牺牲品。这使主 txn 执行完成。您需要对主 txn 使用 SERIALIZABLE 隔离级别。其他 txns 在死锁时收到错误 (1205),因此回滚它们的事务并重新启动它们。
有关死锁检测和处理的更多信息,您可以参考http://technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx。
这个怎么样...
using (var transaction = new TransactionScope())
{
Context.Database.ExecuteSqlCommand("DELETE Items WITH (TABLOCKX)");
SqlBulkCopyHelper.BulkInsert(Context.Database.Connection.ConnectionString, "Items", items);
}
其中“上下文”是我从这里得到的实体框架 DbContext 和 SqlBulkCopyHelper 。
TransactionScope 默认为 SERIALIZABLE,所以我认为表锁将在持续时间内保持。