SSIS : Unable to enlist in a distributed transaction

0

what I am trying to do is to copy some information from Oracle 11 DB (query) to SQL Server 2008 (single table) using SSIS. Apparently I got mixed up with the transaction stuff. While everything executes well when I leave the transaction options to their default values, I get the below error when setting Package Transaction property to Required (or one of the data flow components Transaction properties to Required). So, while trying to execute this DTSX script, I get the following error:

Microsoft (R) SQL Server Execute Package Utility
Version 10.0.2531.0 for 32-bit
Copyright (C) Microsoft Corp 1984-2005. All rights reserved.

Started:  11:38:02 §£
Info: 2013-01-16 11:38:02.45
   Code: 0x4001100A
   Source: issued_import 
   Description: Starting distributed transaction for this container.
End Info
Info: 2013-01-16 11:38:04.52
   Code: 0x4004300A
   Source: Data Flow Task 1 SSIS.Pipeline
   Description: Validation phase is beginning.
End Info
Info: 2013-01-16 11:38:05.01
   Code: 0x40043006
   Source: Data Flow Task 1 SSIS.Pipeline
   Description: Prepare for Execute phase is beginning.
End Info
Error: 2013-01-16 11:38:05.10
   Code: 0xC0047062
   Source: Data Flow Task 1 Source - Query [1]
   Description: System.InvalidOperationException: Unable to enlist in a distributed transaction
   at Oracle.DataAccess.Client.OracleConnection.EnlistTransaction(Transaction transaction)
   at Microsoft.SqlServer.Dts.Runtime.ManagedHelper.GetManagedConnection(String assemblyQualifiedName, String connStr, Object transaction)
   at Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManager100.AcquireConnection(Object pTransaction)
   at Microsoft.SqlServer.Dts.Pipeline.DataReaderSourceAdapter.AcquireConnections(Object transaction)
   at Microsoft.SqlServer.Dts.Pipeline.ManagedComponentHost.HostAcquireConnections(IDTSManagedComponentWrapper100 wrapper, Object transaction)
End Error
Error: 2013-01-16 11:38:05.10
   Code: 0xC004701A
   Source: Data Flow Task 1 SSIS.Pipeline
   Description: component "Source - Query" (1) failed the pre-execute phase and returned error code 0x80131509.
End Error
Info: 2013-01-16 11:38:05.10
   Code: 0x4004300B
   Source: Data Flow Task 1 SSIS.Pipeline
   Description: "component "SQL Server Destination" (102)" wrote 0 rows.
End Info
Info: 2013-01-16 11:38:05.10
   Code: 0x40043009
   Source: Data Flow Task 1 SSIS.Pipeline
   Description: Cleanup phase is beginning.
End Info
Info: 2013-01-16 11:38:05.10
   Code: 0x4001100C
   Source: Data Flow Task 1 
   Description: Aborting the current distributed transaction.
End Info
Info: 2013-01-16 11:38:05.10
   Code: 0x4001100C
   Source: issued_import 
   Description: Aborting the current distributed transaction.
End Info
DTExec: The package execution returned DTSER_FAILURE (1).
Started:  11:38:02 §£
Finished: 11:38:05 §£
Elapsed:  2.823 seconds

Mind that I am not interested in doing a Distributed Transaction - the related service is running on the SQL Server side, but I am pretty sure nothing has been done about it on Oracle side, and probably a distributed transaction SHOULD fail. If this is the case, what other ways are there to tackle this? To wrap my data flow task into BEGIN/END TRANSACTION Execute SQL blocks (like suggested here)?

transactions
ssis
asked on Stack Overflow Jan 16, 2013 by hello_earth • edited May 23, 2017 by Community

1 Answer

1

By changing the default Transaction type from Supported to Required, my, potentially flawed, understanding of the process is that if it's completely on a single SQL Server, the SSIS engine will essentially use a BEGIN TRAN to handle transactions. If more than one server is involved, then SSIS is going to use the Distributed Transaction Coordinator to handle speaking the appropriate language to the listener to get transactions working.

For DB2, we had to explicitly grant some permission (hand waving here as I don't know the specifics) to the account that just wanted to read the data from within a transaction. We had similar troubles with a MySQL source if memory serves correct.

We wanted to use the native transaction stuff because we're lazy programmers but didn't want to go through the hassle of submitting change control requests for all the DB2 data we might want to read under a transaction so our resolution was to create 2 data flow tasks. The Control Flow was left as Supported. The first task ran under the Supported transaction option (NotRequired would have also worked). This task queried the data out of the host system and wrote it to a RAW destination. RAW is a binary file format that SSIS can use very efficiently, is type safe, etc. The second data flow task had transaction set to Required and used the RAW file as a source and then routed to our destination table. Since transactions don't make sense for files, this alleviated the need for MSDTC to work with the non-SQL Server systems which made our lives easier.

There is a cost to this though and that's disk. Anytime SSIS hits disk, you've lost the game. Disk IO hurts and so for large volumes (large depends on your IO subsystem, your SLA for getting data loaded, etc) you're going to read the data out of source system, write to a local system, read that data back in and then eventually write to the target system. That's a lot of reads and writes which SSIS tries to avoid by doing so much in memory. Our volumes were such that this did not impact our performance enough to outweigh the paperwork hassle but only you will be able to make that call after performance testing.

answered on Stack Overflow Jan 16, 2013 by billinkc

User contributions licensed under CC BY-SA 3.0