在处理SSIS包的数据ETL操作过程中,我们经常遇到的一个问题就是一系列步骤在运行的过程中,如果中间的一个步骤失败了,那么我们就需要清理前面已经运行过的步骤所产生的数据或者结果,这往往是一个很头疼的过程。那么在SSIS的 Package中是否可以实现事务机制呢?
我们知道基于事务我们可以保证在一系列操作下的各个步骤,它们要么全部成功,要么全部失败。这里将介绍在SSIS的Package中一个比较简单的实现方法。
首先,建立一个测试表,这个表里会有一个自增的主键标识,然后分别有一个文本和数字类型的字段。脚本如下:
USE [DBTEST]
CREATE TABLE [dbo].[TBTest](
[id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](50) NULL,
[Amount] [decimal](18, 0) NULL,
CONSTRAINT [PK_TBTest] PRIMARY KEY CLUSTERED
(
[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感兴趣可以参考园子里另外一个朋友对它的介绍。
---------------------------------------------------------------
aspnetx的BI笔记系列索引:
使用SQL Server Analysis Services数据挖掘的关联规则实现商品推荐功能
微软SQLServer官方示例项目部署-数据引擎和分析服务部分
使用SQL Server Analysis Services Tabular Model建立分析模型
在Silverlight下用Visifire显示多维数据集中的数据
在Silverlight下用Visifire显示多维数据集中的数据(二)
BI笔记之---SSAS中关于某一度量需要先后根据不通维度的不同聚合方法的解决
BI笔记之---RDLC中读取Analysis Services中Cube的数据