【问题标题】:Preventing from locking database in transaction防止在事务中锁定数据库
【发布时间】:2015-10-11 20:18:54
【问题描述】:

我有更新和插入大量数据的查询:

update [TableA]
set ColumnA1 = 'ValueA1'

DECLARE @MyCursor CURSOR;
DECLARE @MyField char(16);
BEGIN
    SET @MyCursor = CURSOR FOR
    select  ColumnA1 from [TableA]
        Where ColumnA2 = ValueA2  

    OPEN @MyCursor 
    FETCH NEXT FROM @MyCursor 
    INTO @MyField

    WHILE @@FETCH_STATUS = 0
    BEGIN

      FETCH NEXT FROM @MyCursor 
      INTO @MyField 

      Insert Into TableB(ColumnB1, ColumnB2, ColumnB3, ColumnB4, ColumnB5, ColumnB6)
      Values(@MyField, ValueB1, ValueB2, ValueB3, ValueB4, ValueB5)
    END; 

    CLOSE @MyCursor ;
    DEALLOCATE @MyCursor;
END;

正如您所注意到的,我首先更新了 TableA,然后使用更新的 TableA 记录将一些日志信息插入到 TableB。我想以事务方式执行整个 sql 命令。我害怕使用begin transaction 会锁定整个 sql server 数据库。我已经在使用实体框架,但我不知道它如何在不锁定 sql server 的情况下处理此类命令。

【问题讨论】:

  • 别害怕。开始事务不锁定整个 sql server 数据库。

标签: sql sql-server entity-framework


【解决方案1】:

根据 Hamlets 的评论,没有“整个数据库”lock。最接近的可能是将数据库放入single user mode

但是,对高​​度竞争数据的行或表持有广泛(独占)锁会影响同时尝试读取已提交数据的其他查询或其他写入者的性能。

例如由于下面的更新可能会更改所有行,它几乎肯定会在 TableA 上 TABLOCK,因此如果您将整个发布的 SQL 包装在一个事务中,TableA 也将在游标期间被锁定。

UPDATE [TableA]
SET ColumnA1 = 'ValueA1';

光标本身似乎是不必要且不可取的 - 只要有可能,就用基于集合的方法替换 RBAR 方法。下面的插入应该是等效的:

INSERT Into TableB(ColumnB1, ColumnB2, ColumnB3, ColumnB4, ColumnB5, ColumnB6)
SELECT ColumnA1, ValueB1, ValueB2, ValueB3, ValueB4, ValueB5
FROM [TableA]
WHERE ColumnA2 = ValueA2;

为了回答您的最后一个问题,Entity Framework 默认将.SaveChanges() call 包装到a transaction - 到目前为止,对DbContext 所做的所有更改都仅在内存中进行跟踪。

IMO、ORMS 之类的 EntityFramework 并不适合大型批量/批量操作,例如您在此处介绍的 sql,因为您几乎无法控制生成的 Sql。

如果您打算将此批量作业移至 .Net,我可以建议

  • 您可以通过基本的SqlCommand 完成批量更新
  • 使用SqlBulkCopy 可以有效地完成批量插入

您将能够通过共享SqlConnection 控制上述事务(SqlBulkCopy 有一个采用 SqlConnection 的构造函数)。

顺便说一句,如果您的要求不要求您在事务下执行整个操作序列,您可以考虑将更新 + 插入批处理成每次提交 lock escalation issues。

【讨论】:

  • 但我不希望我的表也被锁定!
  • @SeyedMortezaMousavi,除了帖子,您还可以查看隔离级别。
  • @SeyedMortezaMousavi 如果您想围绕所有工作进行事务处理,锁定是不可避免的。但是,您可以选择移动 concurrent Snapshot isolation(从而从悲观锁定转移到乐观锁定)
猜你喜欢
  • 2016-12-13
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多