我只是想问一下,当封装到一个事务时,它是否总是会执行第一个查询?例如,我有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;
答案 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语句的级别,但在日志中没有记录任何内容 应用程序执行修改操作。