SSIS - 序列化/锁定包
Posted
技术标签:
【中文标题】SSIS - 序列化/锁定包【英文标题】:SSIS - Serialize/Lock a package 【发布时间】:2019-07-07 23:15:03 【问题描述】:长话短说,我需要使用 SSIS 在 Netezza 中创建一个序列。
我计划创建一个通用包,它将查找一些表并基于自然键和源,它要么返回代理键(如果存在),要么创建一个新键并将其返回给调用 SSIS 包。
这个包将被多个 SSIS 包调用,每个包对应一个源。我的问题是它们可以同时运行并同时调用这个包,这可能会导致代理键中的唯一性问题。
有什么建议吗?
谢谢
【问题讨论】:
为什么不使用 Netezza 序列?您只是在这里为自己制造困难(且不可扩展)。 Nick-SSIS 仅用于编排。在幕后,无论如何我们都将使用 Netezza 序列。我的问题是我有多个源(每个源一个包/作业),我想尽量减少重构和复制在所有包中创建密钥的相同逻辑。这是一个近期的解决方案,因为要同时迁移到 AWS。一旦该解决方案最终确定,我们将不得不找出不同的东西。我同意您的评论,即这是不可扩展的,而且这张桌子会很热。但这是我能想到的最好的了。非常感谢您的宝贵时间 同一个包被其他包同时调用是没有问题的,如果在幕后它使用一个序列。一个序列保证你会得到一个新的号码。如果可能的话,实际上更好的是,如果您创建一个存储过程,它采用表名和自然键并返回现有或新的代理键。然后你可以从每个包中调用 proc。而不必调用整个子包(还有其他问题,例如未记录、进程用完时的额外开销等) 我也是这么想的,尼克。如果 package1 调用子包,同时 package2 调用,它将进入 30 秒的等待。包 1 可能完成,然后包 3 在包 2 的 30 秒等待时间完成之前调用它。这样,理论上,包 2 可能永远不会轮到它。我将尝试存储过程的方法,并尝试在 POC 中模拟现实生活场景。我会及时通知你们。感谢你的宝贵时间。 PS:我不需要将任何密钥返回给调用包。我只需要更新表格,他们就会在他们的过程中进行查找。 【参考方案1】:创建子(查找)包,然后使用执行包的单个步骤创建 SQL 代理作业。然后你的父包可以执行作业,而不是直接执行包。 SQL 代理将负责“锁定”包,因为作业只能运行一个实例。
您可能需要构建某种等待机制。您可以查询msdb.dbo.sysjobactivity
以确定作业是否正在运行。
我最近构建了一个包,它几乎完全符合您的要求。这是它最终的样子:
在第一个执行 SQL 步骤中,我获取了 JobId 和步骤名称。被调用的过程使用以下查询(我传入@JobName):
SELECT @JobId = job_id
FROM msdb.dbo.sysjobs
WHERE name = @JobName
然后Is the job running
Execute SQL 任务执行以下查询,检查作业是否正在运行:
DECLARE @JobId UNIQUEIDENTIFIER
SET @JobId = ?
SELECT
Running =
CASE
WHEN start_execution_date IS NOT NULL AND stop_execution_date IS NULL
THEN 1
ELSE 0
END
FROM msdb.dbo.sysjobactivity
WHERE job_id = @JobId
我将值保存到一个变量中,然后启用和禁用相应的路径。如果作业正在运行,我等待 30 秒,然后 Wait while job is running
循环重新启动并再次检查作业活动状态。
1 秒的等待是为了给 db 引擎足够的时间来更新作业活动表。我的包失败了,因为它执行检查的速度太快,并且认为可以启动下一次执行作业。通过暂停片刻,我们可以在检查作业活动状态时获得准确的结果。
一旦包到达Start Job Step
,它就会执行以下查询来开始工作:
DECLARE @step VARCHAR(100)
,@Job VARCHAR(100)
SET @step = ?
SET @Job = ?
EXEC msdb.dbo.sp_start_job @job_id = @job, @step_name = @step
如果您的情况不需要指定步骤,因为您的查找包作业将只有一个步骤。
【讨论】:
Aaron- 非常感谢您的解决方案。我会试试这个,让你知道。从概念上讲,对于我正在寻找的东西来说,这听起来很完美。非常感谢。会及时通知您 您不能在作业中传递变量...(即您不能返回代理键)。另外.... 30 秒的等待不会影响您加载 1,000 条记录并尝试查找/生成密钥。以上是关于SSIS - 序列化/锁定包的主要内容,如果未能解决你的问题,请参考以下文章