SSIS transaction management MSSQL - sql-server

I need to copy data from DB "source" to db "destination" should the copying fail, I need to roll back on "destination". The two connections are defined in the connection manager as OLE DB.
Here is my current attempt which is not working. I tried playing around with the in-built transaction managemen (setting the tasks transaction to required) but that only made it impossible to connect to "destination".
The destination has set "RetainSameConnection" = true, while this is false for "source" for no particular reason.
I also set the "MaxConcurrentExecutables" = 1 in to hinder SSIS from executing my rollback as the first thing.
Each of the tasks in the sequence is set to "Isolation level"=ReadUncommitted and "transactionOption"=supported.
The "failing script" is a script that always fail in order for me to test the transaction is working.
The code for the task "begin tran" is "BEGIN TRANSACTION " and the connection is set to "destination"
The Code for the task "rollback tran" is "rollback transaction" and the connection is set to "destination"
The rollback fails with "the rollback transaction request has no corresponding 'BEGIN TRANSACTION'"

You are mixing two concepts here. There are 2 ways to achieve transactions in SSIS. The first is SSIS Transactions. Here, your package should be set to TransactionOption = Supported, you container should be set to TransactionOption = Required (which will begin a transaction) and then your two Data Flow Tasks would need to be set to TransactionOption = Supported, which would make both of them join the open transaction. However, please not that this option requires Distributed Transaction Coordinator and there is no way around that.
The second way of achieving transactions is with SQL Native Transactions. Here, you would have an Execute SQL Task that starts a transaction, followed by your Data Flow Tasks and then another Execute SQL that commits the transaction (and of course another to rollback). The issue here, is that it is a requirement that all of the tasks I have just mentioned Use the same connection manager and that retainsameconnection = True on that connection manager otherwise it will not work, as SSIS and SQl Server still regard it as a distributed transaction, even though they are not on the same server, and you would have to use BEGIN DISTRIBUTED transaction, which again requires Distributed Transaction Coordinator. Also I recall that Distributed Native SQL Transactions do not work properly in SSIS.
The short answer is that you cannot achieve what you are trying to do with transactions in SSIS. An alternative would be to use a compensation block. Here, on failure of insert, you would have an Execute SQL Task that deletes the data you have just inserted, based on either Time, or a SELECT MAX(ID), which ever suits your requirements best.

Related

ssis transaction with out Msdtc

One of the packages is going to implement using
SQL Server Integration Services SSIS Transactions without MSDTC.
The Execute SQL task has placed ,before the data flow(Df_insert) for begin transaction.There are several update steps and index creation steps ,after this First data flow(Df_Insert).There is an update scripts which is in another sequence container and ,need to be part of this transaction.
Is there any way to include only the Df_insert and the update scripts
in the transaction.
The control flow looks like, the below
From SQL Transaction point of view ALL DML statements, i.e. inserts-updates-deletes, between BEGIN TRAN and COMMIT are part of this transaction and not deducible. Your task - committing only DFT and update script - means that update, update2 and delete are temp data used in your update script and discarded later on.
Approach - rework your logic to move results of update, update2 and possibly delete results into TEMP tables and use it afterwards. Regular #temp_table will be fine since you have to use RetainSameConnection=true for transaction without MSDTC.

Using SAVE TRANSACTION with a linked server

Inside a transaction that have a savepoint I have to make a join with a table that is in a linked server. When I try to do it, I get the error message:
“Cannot use SAVE TRANSACTION within a distributed transaction”
The remote table data rarely changes. It is almost fixed. Is is possible to tell SqlServer to exclude this table from the transaction? I've tried a (NOLOCK) hint, but it isn't possible to use this hint for a table in a linked server.
Does anyone knows about a workaround? I'm using the ole SqlServer 2000.
One thing that you could do is to make a local copy of the remote table before you start the transaction. I know that this may sound like a lot of overhead, but remote joins are frequently a performance problem anyway and the SOP fix for that is also to make a local copy.
According to this link, the ability to use SAVEPOINTs in a Distributed transaction was dropped in SQL 7.
To allow application migration from Microsoft SQL Server 6.5 when
savepoints inside distributed transactions are in use, Microsoft SQL
Server 2000 Service Pack 1 introduces a trace flag that allows a
savepoint within a distributed transaction. The trace flag is 8599 and
can be turned on during the SQL Server startup or within an individual
session (that is, prior to enabling a distributed transaction with a
BEGIN DISTRIBUTED TRANSACTION statement) by using the DBCC TRACEON
command. When trace flag 8599 is set to ON, SQL Server allows you to
use a savepoint within a distributed transaction.
So unfortunately, you may either have to drop the bounding ACID transaction, or change the SPROC on the remote server so that it doesn't use SAVEPOINTs.
On a side note (Although I have seen that you have tagged it SQL SERVER 2000) but to make a point that SQL SERVER 2008 has remote proc trans Option for this.
In this case if the distributed table is not too large I would copy it to a temp table. If possible, include any filtering to get the number of rows to a minimum. Then you can proceed normally. Another option since the data changes rarely is copy the data to a permanant table and checking if anything has changed to prevent sending to much data over the network every time you run the transaction. You could only pull over the recent changes.
If you wish to handle transaction from UI level and you have Visual Studio 2008/.net fx 3.5 or + framework then you can wrap your logic with TransactionScope Class. If you dont have any frontends and you are working only on Sql Servers kindly ignore my answer...

Database Connection and Rollback Process

I wonder a case. I have a project using a database (Oracle and Mssql). My project has a framework that I manage transactions.
In thread I open a database connection and start a transaction.(In transaction, there are many update and insert queries.) While code is running, somehow connection is closed. Because I have try-catch block, I catch exception and rollback transaction. BUT; if my connection is closed because some reasons, how rollback query can run on database? How can I handle this situation? If I open a new connection and rollback, does it work?
Thanks.
There is a term you should know - ACID compliancy:
Atomicity is an all-or-none proposition;
Consistency guarantees that a transaction never leaves your database in a half-finished state.
Isolation keeps transactions separated from each other until they’re finished.
Durability guarantees that the database will keep track of pending changes in such a way that the server can recover from an abnormal termination.
Concerning MySQL
In order to get this at MySQL, you have to use Transaction Safe Tables (TST). Advantages of Transaction-Safe Tables:
Safer. Even if MySQL crashes or you get hardware problems, you can get your data back, either by automatic recovery or from a backup + the transaction log.
You can combine many statements and accept these all in one go with the COMMIT command.
You can execute ROLLBACK to ignore your changes (if you are not running in auto-commit mode).
If an update fails, all your changes will be restored.
Concerning SQL Server
You should read "Transaction Behavior On Lost Connection" MSDN forum topic.
To understand better what lays behind MS SQL Server transactions, read a good article "Locks and Duration of Transactions in MS SQL Server"
Make sure you are not using any autocommit feature (I think that's enabled by default in some MySQL installations). If you do all your commits "manually", a broken connection will just result in you never committing the transaction and so it won't ever get written.
You cannot reconnect to rollback in most database systems.

What happens to connections when taking SQl Server Database Offline?

I have recently tried a big merge of 2 databases. We recreated the schema from Database 2 into Database 1 and created a script to transfer all data from database 2 into Database 1. This script takes about 35 min to run and have transaction handling with:
BEGIN TRANSACTION
...
IF(##error<>0)
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
The full script is a bit sensitive but here is some SQL that have the same structure: http://pastebin.com/GWJ3ZnkF
We ran the script and all data was transfered without errors. We tested the systems running with the new combined database (removed access rights to the old database).
But as a last task we wanted to take the old database offline to make sure no one used that database. To do this we used:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
This was bad. After this line of SQL code all data in the combined database that we just copied was suddenly gone. I first asumed it wasn't really finished so the "Rollback immediate" sounds like it have performed a rollback on my transaction..
But why? Wasn't the transaction allready committed?
Also I tried running the same script again a few times but after every attempt no data was copied even if it said the script was successfull. I have no idea why... did it remember my offline rollback somehow?
What is really happening to my connections?
Sounds like you had a pending transaction uncommitted and you forced it to rollback, loosing some of the work. The rest is explained by how your scripts are structured. Is unlikely your script had a single transaction from start to bottom. Only the last transaction was rolled back, so the database was left now in a state in which it is 'half copied'. Probably your script does various checks and this intermediate state sends the script on the 'ELSE' branches where it does not do the proper work (ie. apparently does nothing).
W/o posting the exact script, is all speculation anyway.
Right now you need to restore the database to a consistent state, the one before your data copy. Use the backup you took before the data move (you did take a backup, right?). for extra credit, make sure your script is idempotent and works correctly on a half-updated database.
I'd double-check to make sure that there are no outstanding transactions. Either go through the file and count the number of BEGIN TRANSACTION vs COMMIT TRANSACTION lines, or add a statement to the end of it to SELECT ##TRANCOUNT to ensure that there are no open transactions remaining.
If your data has been committed, there should be no way it can be lost by disconnecting you.
WITH ROLLBACK IMMEDIATE:
All incomplete transactions will be rolled back and any other
connections to the database will be
immediately disconnected.
Sounds like someone got the 2 databases mixed up or maybe there is an outstanding transaction?.... Can you post your entire script?
Ref: ALTER DATABASE.
Rather than only checking ##ERROR, inspect ##TRANCOUNT as well.

How do I fix the error unable to enlist Sybase database in distributed transaction?

I know very little (arguably nothing) about Sybase setup, but I do know SSIS is having trouble enlisting Sybase in a distributed transaction. Has anyone been able to make this work?
The SSIS Runtime has failed to enlist the OLE DB connection in a
distributed transaction with error 0x80004005 "Unspecified error".
This happens when I change the package's TransactionOption to Required. When I revert to the default "Supported", the package runs without errors (albeit not thread safe).
I had this same problem when I tried to create a transaction around a read from a Gupta SQLBase. Basically, it seems that SSIS (at least as of 2005) isn't able to enroll any other providers in a transaction as part of a package. I've tried a few times without luck, and usually I just end up reading the data from my OLEDB into a temporary table, and then creating a transaction around the import of that data into its resting place in SQL Server. That's the read side, though - if you're trying to use a transaction to write to SYBASE, you'll need to do something on that side - SSIS won't be able to use a transaction to push data to another provider.
I addition to that, I didn't even want my transaction to extend to Gupta - I only wanted to enroll my INSERT/UPDATE on the SQL Server side in a transaction, to block users from reading half-updated data, but SSIS refused to allow me to wrap the process in a transaction because Gupta didn't support it. There seems to be no support for transactions just on certain providers, or only on the "Write" side of the process but not on the "Read" side.

Resources