Re: Transaction handling with Oracle DBD
- From: chuckfox2@xxxxxxx
- Date: Mon, 25 Apr 2005 10:17:15 -0400
Personally, I would rewrite the sql to perform inside of do's
$dbh->do("INSERT INTO data_tab (counter) SELECT counter FROM count_tab" )
or die "Couldn't prepare statement: " . $dbh->errstr;
$dbh->do("UPDATE count_tab SET counter = counter + 1" )
or die "Couldn't prepare statement: " . $dbh->errstr;
However, the OP is probably testing out the waters and eventually wants to use the counter in some manipulation in perl. In that case,
1. Move the connect statement outside of the loop, you are unnecessarily creating and destroying it. This will speed execution of the code immeasurably. (well its measurable, but don't bother)
2. Since you are executing the same statements in a loop, consider using a prepared statement. This will also speed the code as you are not compiling the sql each time.
3. Batching the transactions together into groups of 100 or more may add more speed to the operation. This is because the overhead of the update to the one table can be resolved by the server's transaction manager and only the final update of the batch applied. Also, servers work better when you are doing something over and over and it can be done is a result set oriented manner as opposed to one row/transaction at a time.
Following code is untested! YMMV, UAYOR!
#!/usr/bin/perl
use DBI;
# DB name used by Perl Script
$PS_DBNAME = "DBI:Oracle:xyz";
$DB_USERID="abc";
$DB_PASS="def";
my $dbh = DBI->connect(PS_DBNAME, $DB_USERID, $DB_PASS)
or die "Couldn't connect to database: " . DBI->errstr;
my $sel_stmt = $dbh->prepare( "SELECT counter FROM count_tab" )
or die "Couldn't prepare statement: " . $dbh->errstr;
my $ins_stmt = $dbh->prepare( "INSERT INTO data_tab (counter) VALUES(?)")
or die "Couldn't prepare statement: " . $dbh->errstr;
my $upd_stmt = $dbh->prepare( "UPDATE count_tab SET counter = ?")
or die "Couldn't prepare statement: " . $dbh->errstr;
$counterval = 0;
$i = 0;
for($i=0; $i<100; $i++)
{
$dbh->begin_work;
eval
{
$sel_stmt->execute()
or die "Couldn't execute statement: " . $sth->errstr;
# there should be only one row
while (@data = $sel_stmt->fetchrow_array())
{
$counterval = $data[0];
}
$ins_stmt->execute( $counterval )
or die "Couldn't execute insert statement: " . $dbh->errstr;
$counterval = $counterval + 1;
$upd_stmt->execute($counterval)
or die "Couldn't execute update statement: " . $dbh->errstr;
};
if ($@)
{
$dbh->rollback;
}
else
{
$dbh->commit;
}
}
$dbh->disconnect;
exit 0;
Your Friendly Neighborhood DBA,
Chuck
-----Original Message-----
From: RKris <caissark@xxxxxxxxx>
To: dbi-users@xxxxxxxx
Sent: Sat, 23 Apr 2005 08:30:56 -0700 (PDT)
Subject: Transaction handling with Oracle DBD
Hi, I am getting data corruption when I attempt to run
several processes in parallel when making changes to
two tables.
DBD version 1.16, DBI version 1.48, Linux 2.6, Oracle
9i.
I am trying to select a counter value from table 1,
insert it into table 2 and update table 1 counter
value. This comprises a transaction. I do this 1000
times in a 'for' loop. Even after I clear out the
counter value in table 1 and run the test with two
processes, I am getting a value of 3000 in the
counter!
I included the code below. I moved the connect into
the 'for' loop as I read connect automatically starts
a transaction. Please let me know if I am doing
something wrong! Thanks a lot.
#!/usr/bin/perl
use DBI;
# DB name used by Perl Script
$PS_DBNAME = "DBI:Oracle:xyz";
$DB_USERID="abc";
$DB_PASS="def";
$counterval = 0;
$i = 0;
for($i=0; $i<100; $i++)
{
my $dbh = DBI->connect(PS_DBNAME, $DB_USERID,
$DB_PASS)
or die "Couldn't connect to database: " .
DBI->errstr;
$dbh->begin_work;
eval
{
my $sth = $dbh->prepare('SELECT counter FROM
count_tab')
or die "Couldn't prepare statement: " .
$dbh->errstr;
$sth->execute()
or die "Couldn't execute statement: " .
$sth->errstr;
# there should be only one row
while (@data = $sth->fetchrow_array())
{
$counterval = $data[0];
}
$dbh->do("INSERT INTO data_tab (counter)
VALUES($counterval)")
or die "Couldn't prepare statement: " .
$dbh->errstr;
$counterval = $counterval + 1;
$dbh->do("UPDATE count_tab SET counter =
$counterval")
or die "Couldn't prepare statement: " .
$dbh->errstr;
$sth->finish;
};
if ($@)
{
$dbh->rollback;
}
else
{
$dbh->commit;
}
$dbh->disconnect;
}
exit 0;
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
- References:
- Transaction handling with Oracle DBD
- From: RKris
- Transaction handling with Oracle DBD
- Prev by Date: RE: Problems building DBI on Windows
- Next by Date: chart_map_modifier in DBD::Chart
- Previous by thread: Re: Transaction handling with Oracle DBD
- Next by thread: Problems building DBI on Windows
- Index(es):
Relevant Pages
|
|