我无法重现您的问题。根据您的描述,我假设您的包裹看起来像这样。SO_retain OLE 连接管理器指向我正在工作的数据库,并将 RetainConnection 属性设置为 True。
我为事件 OnError 和 OnPre/PostExecute 添加了日志记录。我跑了两次包裹。一次使用 SO_retain 连接管理器,一次使用 SO_no_retain。
执行后,我查询日志以查看发生了什么。SELECT L.id, L.event, L.source, L.executionid FROM dbo.sysdtslog90 L ORDER BY 1;
如果您使用的是 2008/2008R2,请将表修改为 dbo.sysssislog。
我的结果是
1 PackageStart so_Andre_LoggingTrxn B2D17896-199F-4213-B800-E812CE95D45F
2 OnPreExecute so_Andre_LoggingTrxn B2D17896-199F-4213-B800-E812CE95D45F
3 OnPreExecute Begin tran B2D17896-199F-4213-B800-E812CE95D45F
13 OnPostExecute Rollback B2D17896-199F-4213-B800-E812CE95D45F
14 OnPostExecute so_Andre_LoggingTrxn B2D17896-199F-4213-B800-E812CE95D45F
15 PackageEnd so_Andre_LoggingTrxn B2D17896-199F-4213-B800-E812CE95D45F
16 PackageStart so_Andre_LoggingTrxn F6898ECA-46E7-4760-8885-898FADCBEFFD
17 OnPreExecute so_Andre_LoggingTrxn F6898ECA-46E7-4760-8885-898FADCBEFFD
18 OnPreExecute Begin tran F6898ECA-46E7-4760-8885-898FADCBEFFD
19 OnPostExecute Begin tran F6898ECA-46E7-4760-8885-898FADCBEFFD
20 OnPreExecute Sequence Container F6898ECA-46E7-4760-8885-898FADCBEFFD
21 OnPreExecute Divide by zero F6898ECA-46E7-4760-8885-898FADCBEFFD
22 OnError Divide by zero F6898ECA-46E7-4760-8885-898FADCBEFFD
23 OnError Sequence Container F6898ECA-46E7-4760-8885-898FADCBEFFD
24 OnError so_Andre_LoggingTrxn F6898ECA-46E7-4760-8885-898FADCBEFFD
25 OnPostExecute Divide by zero F6898ECA-46E7-4760-8885-898FADCBEFFD
26 OnPostExecute Sequence Container F6898ECA-46E7-4760-8885-898FADCBEFFD
27 OnPreExecute Rollback F6898ECA-46E7-4760-8885-898FADCBEFFD
28 OnPostExecute Rollback F6898ECA-46E7-4760-8885-898FADCBEFFD
29 OnPostExecute so_Andre_LoggingTrxn F6898ECA-46E7-4760-8885-898FADCBEFFD
30 PackageEnd so_Andre_LoggingTrxn F6898ECA-46E7-4760-8885-898FADCBEFFD
正如您所看到的,事情正在按照人们对交易的预期发生。在第一次执行中,包开始触发记录的事件(PackageStart、OnPreExecute)。源“Begin tran”的 OnPreExecute 是我们看到的最后一件事,直到“Rollback”的 OnPostExecute 触发。但是,ID 之间存在差距。该间隙是在事务下发生的所有插入。该事务被回滚,因此所有这些工作都被撤消,唯一的指标是消耗的身份值。
当我更改日志记录以将 SO_no_retain 用于连接管理器时,我看到正在记录 OnError 事件。
编辑
您在日志中看到了第一组条目,但希望看到第二组条目。
了解为什么会这样是交易如何运作的基础。一个事务将工作声明打包成一个单独的块,这些东西都可以工作,或者都将失败。在您的事务中,程序包正在发出 sp_ssis_addlogentry 命令。当前事务内部没有办法说“使这些语句比其他语句更持久”或“在当前事务之外保留这些语句”。全有或全无,这是交易上下文中的唯一选择。
鉴于此,您的选择是创建第二个专用于日志记录的连接管理器,正如我在 SO_no_retain CM 中展示的那样,或者编写您自己的错误日志记录系统。我真的,真的会提倡前者,因为它是原生行为。否则,您将花费大量时间
第三种选择
这件事让我印象深刻,也许你没有意识到这一点。您不需要 begin tran /commit/rollback 模式。SSIS 可以为您开箱即用地做到这一点。根据包运行的位置,它需要运行 MSDTC(MS 分布式事务协调器),但简而言之,你告诉包你想让这些组件在事务中登记,瞧,奇迹发生了,你不要不必管理它。SSIS 中的每个任务都有一个 TransactionOption 的属性。默认情况下,它设置为支持。
交易选项设置
- 支持如果事务存在,则任务将加入其中。它不会启动事务。
- 必需这将启动一个事务。如果一个已经存在,那么它将加入该事务
- NotRequired这不会启动事务,也不会参与正在进行的事务。您可以通过尝试操作相同资源的必需和非必需对象来使自己陷入僵局,因此请注意您在做什么。
鉴于上述包,我会做的是
- 删除协调事务的执行 SQL 任务,
- 将 RetainSameConnection 属性保留为 False
- 在控制流级别(或序列容器),我会将 TransactionOption 设置为 Required
完成,就是这样。当包运行时,“工作”被回滚,但日志记录,包括错误,将在那里。老实说,我写的每个包看起来都差不多。我从来没有理由尝试控制我自己的交易,因为我可能愚蠢地相信交易协调员会处理所有这些。不过,在与 SSIS 合作的 7 年中,我没有遇到 MSDTC 不处理它的问题。