SSIS包执行时OLEDB目标出现主键冲突,已截断表该排查什么?
这种情况我之前踩过好几次坑——明明确认截断了目标表,数据流任务还是报主键冲突,大概率是执行逻辑、数据本身或者环境的细节没注意到,你可以从以下几个点逐一排查:
确认控制流的执行依赖关系
别光看任务的摆放位置,一定要检查Execute SQL任务和DFT之间的成功依赖箭头是否正确建立。比如有没有可能不小心把约束改成了“完成时执行”(不管成功失败都跑DFT)?或者包的其他分支有没有并行执行的任务,在往同一个目标表写数据?另外,可以在Execute SQL之后加个临时的Execute SQL任务,执行SELECT COUNT(*) FROM 目标表,把结果存到变量里,然后用脚本任务判断行数是否为0,确保截断后目标表确实是空的再执行DFT。验证截断操作的准确性
你说Execute SQL确实在执行,但要确认是不是截断了正确的表:比如是不是写错了表名、Schema(比如目标表是dw.TargetTable,但你写的TRUNCATE TABLE TargetTable,默认Schema是dbo的话就会截断错表)。另外,要排查有没有外部进程在干扰——比如目标表有没有触发器自动插入数据?或者ETL之外有定时作业在往这个表写数据?可以在截断后手动查一下目标表的行数,确认是空的。检查源数据的主键唯一性
别想当然认为源表的主键是唯一的!有可能源表的主键约束被临时禁用了,或者上游数据导入时引入了重复值。直接跑个SQL查源表的重复主键:SELECT 主键列名, COUNT(*) AS 重复次数 FROM 源表名 GROUP BY 主键列名 HAVING COUNT(*) > 1如果查到重复值,那不管目标表是不是空的,插入都会报主键冲突,这时候得先清理源数据。
排查数据流任务的插入逻辑
检查DFT里的OLEDB目标是不是用了追加(Append)模式(这个模式本身没问题,但源有重复就会报错);另外,有没有可能DFT里有多个分支往同一个目标表写数据?比如不小心复制了目标组件,或者分流逻辑导致同一条数据被多次插入。还有,看看错误输出的设置——是不是把主键冲突的错误设成了“忽略”,但其实冲突已经存在,只是你没及时发现?检查事务配置
虽然TRUNCATE是DDL语句默认自动提交,但如果包或者任务的事务设置有问题也可能出问题:比如Execute SQL在一个未提交的事务里,DFT在另一个事务里,导致DFT看不到截断的结果?或者任务的事务选项被改成了“不支持事务”,导致截断操作没有生效?可以检查包的TransactionOption属性,以及每个任务的事务设置。确认目标表的主键约束
虽然概率不高,但可以确认下目标表的主键约束是不是正确的:比如是不是复合主键,你只检查了其中一列?或者主键约束有没有被意外修改?不过如果约束不存在的话不会报主键冲突,所以这个更多是确认源和目标的主键定义完全一致。
内容的提问来源于stack exchange,提问作者hieko

