Transactional Control

I want to update two tables together and either commit the changes to both or roll them back.

My understanding is that checking “Include in Transaction” on both target tables should achieve this as long as the tables are from the same datastore, which they are.

The problems I get are
a) I get an error saying that I have to set the sequence number if I leave the Transaction order fields blank
b) After I have set the sequence number / Transaction order and I get an error in the load of the second table the updates to the first are not rolled back.

Does anyone know what I am doing wrong here?

Thanks in advance.

John


johnb (BOB member since 2006-07-05)

Yes, you have to set a transaction order, otherwise it is a syntax error.

But then, if you are really really really using one datastore for both tables it should work. What’s the error message you get? Turn the trace options “trace sql loader” and “sql only” on and check if you see something unusal there. Reduce the number of rows for this test first.


Werner Daehn :de: (BOB member since 2004-12-17)

Hi and thanks for your response.

The only error message that I am getting is the database error which is a violation of a primary key on the second table. Obviously I am expecting this as this is the deliberate error condition that I have created to try and create a rollback for the updates to the two tables.

With the trace options on that you suggested I get:-

Usual startup messages for the job, workflow and dataflow.
Three SQLLOAD logs, one for each table (one is a temp table in a separate data store and two are the ones in the same data store that should be in the same transaction). Each SQLLOAD line says

After the SQLLOAD for the third table (i.e. the second table in the transaction) I get the messages

I have tried removing the try/catch block around the dataflow but this hasn’t made any difference.

Do you have any ideas?

Thanks in advance.

John.


johnb (BOB member since 2006-07-05)

Try that with the two tables only. If it is still not working, send us the ATL. If it is working then, … send me the original ATL as well.


Werner Daehn :de: (BOB member since 2004-12-17)

Hi.

using only two data sources doesn’t make any difference.

Can you give me your email address so that I can send you the ATL?

John


johnb (BOB member since 2006-07-05)

just place it here as attachment.


Werner Daehn :de: (BOB member since 2004-12-17)

Hi.

I’ve created a tiny demo job to illustrate the problem.

Here is a SQL script with definitions of the tables and their contents and also an ATL script with a very simple job to fill them.

John
TwoTableUpdateProblem.atl.txt (19.0 KB)
CreateAndFillTables.sql.txt (0.0 KB)


johnb (BOB member since 2006-07-05)

Looks good to me. Please file a bug in support. I guess it is SQL Server related. Will try later on Oracle.


Werner Daehn :de: (BOB member since 2004-12-17)

OK, willdo.

Thanks for all your help (and for proving that I’m not going mad)

John


johnb (BOB member since 2006-07-05)

Quick update for anyone who is interested.

This has been confirmed by BObj as a bug (bug number 36015)

John


johnb (BOB member since 2006-07-05)

:cuss:

:mrgreen:


Werner Daehn :de: (BOB member since 2004-12-17)

Does any body tested this on Oracle 10g.

I have a source table with opcode column, which specify if the record has to be Inserted/Deleted/Updated, values (I/U/D)

So for Insert, I am generated keys, for Updated and Delete I have Natural Keys coming from Source which I used to do the necessary operation.

So I have this flow

Source ==> Case ==I====> Key_gen ==> Target A
…==U====>Update ===> Target A, based upon Natural Key
…==D====>DELETE ===> Target A, based upon Natural Key

I have included Transaction Number at the target table level as 1 for Inserts, 2 for Deletes ,3 for Updates

But apart from Inserts, nothing works, there is no Update/Delete operation taking place.

I have Marked Natural_Key as my primary key just before the Map_Operation.

Any idea whats wrong here!

We are on 11.7.3 on Windows Server 2003 and Oracle 10g DB
Source is on Different Schema than Target.

If, I create different DF for Inserts/Updates/Delete then it works!, but not with Transaction Control logic concept.

Thanks,


data_guy :us: (BOB member since 2006-08-19)

For these kinds of problems I would always execute the job with the trace_sql_loader flag turned on. Then you can see if updates are executed at all and what values are used.

The natural key is marked as primary key, fine, the loader has to use it, meaning the “use input primary key” option has to be set in the loader options.

One more thing, look at the Map_CDC transform, it is meant for that and it also deals with the case where your source has multiple changes for the same key, e.g. better to insert first and then update a natural key.


Werner Daehn :de: (BOB member since 2004-12-17)

Thanks for the input WeRner,

I have selected “Use Input keys” for both Update and Delete operation.
I enabled “Trace SQL”, seems like correct SQL is generated.

Below is the Data that am trying to test.

OPCODE…TYPE…NATURAL_KEY…DESCRIPTIONS

I…ALPHAFILEFOLDER…ALPHAFILEFOLDER…Expanding File Folder
I…BIN…BIN…x-ray, cassette, disk, Hold paps bin
I…DRW5-9…DRW5-9…5" Drawer to hold 9 containers
I…SLH25…SLH25…Slide holder - 25 position
I…SLIDES DRAWER…SLIDE DRAWER…3" for slide storage
I…SLIDES3-78…SLIDES3-78 …3" drawer 78 alpha/numeric pos. for ES5M slide holders
U…SLIDE DRAWER…SLIDE DRAWER…3" for slide storage
D…SLH25…SLH25…Slide holder - 25 position

For inserts I have to generate keys, which am doing using ORacle Sequences, while for Delete/Updates I have to use NATURAL_KEYS.
untitled1.GIF


data_guy :us: (BOB member since 2006-08-19)

okay, what is the update statement and its values for

U…SLIDE DRAWER…SLIDE DRAWER…3" for slide storage


Werner Daehn :de: (BOB member since 2004-12-17)

Hi Werner,

This is the Inserts Statement
I…SLIDES DRAWER…SLIDE DRAWER…3" for slide storage

that should get updated by this statement
U…SLIDE DRAWER…SLIDE DRAWER…3" for slide storage

based upon third column, which is the Natural key, “SLIDE DRAWER”.

I even tried this on Informix DB 9.40.FC6X3, my jobs just hangs!

I just want to confirm this before, I bring this to my PM, so that we can file case with BO.

Thanks,


data_guy :us: (BOB member since 2006-08-19)

My guess: A timing issue and the solution is Map_CDC.

Your source contains this data you said:

I…ALPHAFILEFOLDER…ALPHAFILEFOLDER…Expanding File Folder
I…BIN…BIN…x-ray, cassette, disk, Hold paps bin
I…DRW5-9…DRW5-9…5" Drawer to hold 9 containers
I…SLH25…SLH25…Slide holder - 25 position
I…SLIDES DRAWER…SLIDE DRAWER…3" for slide storage
I…SLIDES3-78…SLIDES3-78 …3" drawer 78 alpha/numeric pos. for ES5M slide holders
U…SLIDE DRAWER…SLIDE DRAWER…3" for slide storage
D…SLH25…SLH25…Slide holder - 25 position

So you get two rows for the same primary key SLIDE DRAWER, a first insert and a second update. You split the rows into different routes, insert goes in one branch, update into the other.

Now you have two possible effects:

  1. As you did not control it, it could happen the update is executed before the insert. Why not? You have two loaders, each with its own session and no control over the transaction order.
  2. Usually we do array operations, e.g. collect the first 1000 rows and then insert or update them. So in your case the one session collects 1000 inserts, the session of loader2 collects 1000rows for updates and then they are executed in parallel resulting in a database lock as you try to insert and update the same row at the same time.

Turning on transactional loaders is no option either, what if the source is a insert-update-delete-insert-update? Execute the two inserts for the same key twice, then delete them and the update? Certainly not.

With Map_CDC the order of the rows is preserved as no split happens. In fact in the Map_CDC you can specify the order of the statements, e.g. using a timestamp, to make sure the oldest operation is executed first.


Werner Daehn :de: (BOB member since 2004-12-17)

That make sense Werner.

Map_CDC works great if you have primary key at the source, or you are not generating PK for new Inserts every time in target table.

In my case, I have to generate Primary key for each new INSERTS using ORA SEQUENCE in to the Target, and use Natural Key for Update/Delete operation!

My DB is ORA, I don’t think I can set something at DB level, so that it will generate PK automatically for each new Inserts, just like Identity column in SQL Server.

Am, I missing some thing here about Map_CDC transformation?

OK, we used Triggers to generate PK, works fine!

If I used ORA_SEQ before the MAP_CDC transform, then I loose key for operation Updates and Deletes.

Thanks,


data_guy :us: (BOB member since 2006-08-19)

I actually would use an on-insert-trigger to overwrite the primary key with the sequence number. If an Oracle sequence has to be used instead of key_gen.


Werner Daehn :de: (BOB member since 2004-12-17)