是否可以从活动(大量数据移动)存储过程中释放事务日志锁?
Posted
技术标签:
【中文标题】是否可以从活动(大量数据移动)存储过程中释放事务日志锁?【英文标题】:Is it possible to release Transaction-log locks from within an active (massive data movement) stored procedure? 【发布时间】:2019-06-08 18:14:45 【问题描述】:为准确而编辑的术语:
我们的数据集市内每天都有大量数据流。一些最大的,由 SSIS 管理的存储过程完成,需要几个小时。这些长时间运行的存储过程正在阻止清除事务日志(这使问题更加复杂,因为我们同时运行了许多 SP,然后它们都写入 T 日志而没有截断)。最终这会破坏我们的数据库,我们不得不从早上的快照中恢复。
我们已经探索过在 SP 中执行“sub”-commits,但据我了解,您无法在活动存储过程中完全释放事务日志,因为它本身就是一个事务。
如果不重构我们的大型 SP 以分批运行或类似的效果,是否可以在活动 SP 中定期提交事务日志,以便我们释放事务日志上的锁定?
编辑/扩展:
也许我上面错了: 在 SP 中间歇性提交是否会导致事务日志被截断?
【问题讨论】:
不确定您在哪里听到的,但存储过程不是事务。您绝对可以将程序分解为多个单元以减轻事务日志的压力。 听起来你的调用代码一定是在开启交易 你们俩可能都是对的。但是我们肯定会被告知,我们长期运行的 SP 正在执行大型插入或表创建(这肯定是与 SP 的事务)正在锁定事务日志。我们尝试分批插入每个由commit
子句终止的子句,但这会引发破坏我们的 SSIS 作业的警告,而且我们不相信它正在释放事务日志。
日志备份开始时可能存在长时间运行的事务。在这种情况下,释放空间可能需要另一个日志备份。请注意,长时间运行的事务会在所有恢复模式下防止日志截断,包括简单恢复模式,在这种模式下,事务日志通常在每个自动检查点被截断。 docs.microsoft.com/en-us/sql/relational-databases/logs/…
默认情况下,SQL Server 使用自动提交事务,并且每个事务在每个语句之后提交。如果您发现情况并非如此,那么大概是 SSIS 将其包装在事务中。检查 SSIS 包中的 TransactionOption
属性
【参考方案1】:
在 SP 中间歇性提交是否会导致事务日志被截断?
如果客户端启动事务,则不建议在存储过程中提交该事务。 不允许使用与输入时不同的@@trancount 退出存储过程。
技术上允许以下模式,尽管我从未见过它在现实世界中使用过:
use tempdb
if @@trancount > 0 rollback
go
drop table if exists T
create table T(id int identity)
go
create or alter procedure tranTest
as
begin
insert into T default values
commit transaction
begin transaction
end
go
begin transaction
exec tranTest
select * from T
rollback
go 5
如果客户端代码回滚事务而不回滚存储过程的工作,这将是非常令人困惑的。
如果客户端不启动事务,则存储过程中可以有多个事务,但事务的最小粒度是单个 DML 语句。因此,每个 INSERT、UPDATE、DELETE 或 MERGE 都将在单个事务中运行。
对此的实际解决方案是,按好坏的降序排列:
1) 增加可用于日志文件的存储空间以容纳事务。
2) 重构 ETL 以使用更短的事务,可能在声明表中准备好数据并在单个最终事务中加载或切换它
3) 重构 ETL 以小批量运行。
【讨论】:
我们有相当大的事务日志可用。问题是当我们有一个长时间运行的 SP(12 小时以上)时,所有其他运行的线程也对事务日志有贡献,我们很容易超越太字节标记。关于建议3:我们可以在一个SP内做批处理吗?这比重构 SP 以从外部迭代运行要容易得多。如果是这样,如果您提供一个简单的语法演示来说明这将是非常有帮助的 - 我们的尝试导致了破坏 SP 的高严重性警告。 评论太长:续:具体来说,我们如何在每个批次之后在this 之类的内容中提交?这是我们首选的解决方案,因为它允许我们仅在插入点对十几个有问题的大型 SP 进行更改,而不是进行更大的重构。 除非客户端或服务器代码启动事务,否则 SQL Server 将在每个 DML 语句之后提交。 您能否确认一下,如果我们分批插入,每个执行的插入都将被提交,即使 SP 被取消、超时或以其他方式失败(不会滚动完成的插入实例背部)?这实际上是我们在这种情况下想要的行为。 是的。我可以确认,除非客户端已启动事务(或将会话设置为隐式事务),否则将提交每个完成的 INSERT 语句。以上是关于是否可以从活动(大量数据移动)存储过程中释放事务日志锁?的主要内容,如果未能解决你的问题,请参考以下文章