在处理SSIS包的数据ETL操做过程当中,咱们常常遇到的一个问题就是一系列步骤在运行的过程当中,若是中间的一个步骤失败了,那么咱们就须要清理前面已经运行过的步骤所产生的数据或者结果,这每每是一个很头疼的过程。那么在SSIS的Package中是否能够实现事务机制呢?html
咱们知道基于事务咱们能够保证在一系列操做下的各个步骤,它们要么所有成功,要么所有失败。这里将介绍在SSIS的Package中一个比较简单的实现方法。模块化
首先,创建一个测试表,这个表里会有一个自增的主键标识,而后分别有一个文本和数字类型的字段。脚本以下:测试
USE [DBTEST] spa
CREATE TABLE [dbo].[TBTest]( 设计
[id] [int] IDENTITY(1,1) NOT NULL, 3d
[Title] [nvarchar](50) NULL, htm
[Amount] [decimal](18, 0) NULL, blog
CONSTRAINT [PK_TBTest] PRIMARY KEY CLUSTERED 事务
( ci
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
在SSIS下新创建一个Package,而后加入以下三个步骤:
首先将数据表中的数据清空,而后INSERT几条数据,最后尝试进行一个失败的更新。
在LOAD DATA步骤中,简单的手动插入几条数据。
数据源语句的查询。
而后在第三步更新数据的步骤中,咱们尝试对主键进行更新,这里的目的主要就是要引起一个异常而后让后续介绍的事务进行回滚。
首先看一下直接运行的结果。
能够看到在第三步中触发的异常。
而且在表中能够看到,数据确实没有被回滚,还在表中。
接下来,咱们开始尝试在这个Package中加入事务机制。
如上图,SSIS的这种模块化真的是很是好,相信你们一看这个图就马上明白接下来要作什么了。
在BEGINTRAN模块中的代码:
BEGIN TRANSACTION;
在COMMITTRAN模块中的代码:
COMMIT TRANSACTION;
最后,在ROLL BACK模块中的代码:
ROLLBACK TRANSACTION;
而后,运行包。
发如今ROLL BACK模块中仍是报错了,错误信息以下:
而且,事务没有回滚。在表中仍是能够看到被INSERT的数据。
这里的关键在于,每个模块默认利用SSIS里的数据源链接,都是从新开启一个新的链接,因此这样在一个新链接里的ROLLBACK没有前文,确定是要失败的。
因此,这里须要关注SSIS包数据源链接的一个属性,就是RetainSameConnection,它默认为False,把它设置成True,就能够保证在一个包里调用的数据源链接都是同一个链接。
设置好这个属性以后,咱们再来运行下包。
能够发现,当数据流在有异常被触发的时候,ROLL BACK模块成功的进行了回滚。
从表中发现,数据确实被回滚了。
其实实现数据回滚的方法也不少,这是利用SSIS自带功能的一个实现,他确实实现起来相对简单一些。这样能够避免包失败后,从新运行包致使前面的步骤被重复运行。园子里另一个兄弟BI Work介绍的这篇文章利用Check Point来避免这种状况的发生。除此以外,也能够在设计Package的时候,在包的开头就设计好对可能影响到的数据的清理工做。总之实现的方法不少,在实际项目中彻底能够根据实际的状况来决定使用哪个方案。
另外,在SSIS中实际上也能够利用MSDTC,可是它实现起来多少有必定的门槛,若是你对MSDTC感兴趣能够参考园子里另一个朋友对它的介绍。