删除并插入一个事务SQL

时间:2014-10-13 11:00:54

标签: sql sql-server

我只是想问一下,当封装到一个事务时,它是否总是会执行第一个查询?例如,我有500 k记录要删除,500 k要插入,是否有可能锁定? 实际上我已经测试了这个查询,它运行正常,但我想确定我的假设是否正确。

注意:这将删除并插入相同的记录,并在其他列上进行更新。

BEGIN TRAN;
    DELETE FROM OUTPUT TABLE WHERE ID = (1,2,3,4 etc)
    INSERT INTO OUTPUT TABLE Values (1,2,3,4 etc) 
COMMIT TRAN;

2 个答案:

答案 0 :(得分:6)

在事务中,所有写锁定(为修改而获取的所有锁定)必须遵守strict two phase locking规则。其中一个后果是在事务提交之前无法释放在事务中获取的写(X)锁。所以,是的,DELETE和INSERT将按顺序执行,并且在执行INSERT时将保留在DELETE期间获取的所有锁。

请记住,在事务中删除500k行会将锁升级为一个表锁,请参阅Lock Escalation

删除500k行并在单个事务中插入500k行,虽然可能是正确的,但这不是一个好主意。如果可能的话,你应该避免这么大的工作单元,长期交易。长事务将日志固定到位,创建阻塞和争用,增加恢复和数据库启动时间,增加SQL Server资源消耗(锁需要内存)。

您应该考虑小批量操作(可能是10000行),使用MERGE而不是DELETE / INSERT(如果可能),最后但并非最不重要的是,考虑一个分区滑动窗口 实施,请参阅How to Implement an Automatic Sliding Window in a Partitioned Table

答案 1 :(得分:1)

来自documentation on TRANSACTION(强调我的):

  

BEGIN TRANSACTION表示a引用的数据的点   连接在逻辑上和物理上是一致的。如果有错误   遇到,在BEGIN TRANSACTION之后进行的所有数据修改   可以回滚以将数据返回到此已知状态   一致性。 每笔交易都会持续到没有完成   发出错误和COMMIT TRANSACTION以进行修改a   数据库的永久部分,或遇到错误和所有   使用ROLLBACK TRANSACTION语句擦除修改。

     

BEGIN TRANSACTION为连接启动本地事务   发表声明。 取决于当前的事务隔离   级别设置,为支持Transact-SQL而获取的许多资源   连接发出的语句被事务锁定   直到完成COMMIT TRANSACTION或ROLLBACK   交易声明。交易长期处于未偿还状态   时间可以阻止其他用户访问这些锁定的资源,   并且还可以防止日志截断。

     

虽然BEGIN TRANSACTION开始本地交易,但事实并非如此   记录在事务日志中,直到随后的应用程序   执行必须记录在日志中的操作,例如执行   INSERT,UPDATE或DELETE语句。应用程序可以执行   获取锁以保护事务隔离的操作   SELECT语句的级别,但在日志中没有记录任何内容   应用程序执行修改操作。