On 18/05/11 13:10, Shree wrote:
I don't think we can help you because we don't know what HandleIds() does. I
note it may return -1 and causes all of the remaining ids in your batch to be
skipped. Some further comments below:
use strict;
use warnings;
my $dsn = 'dbi:Oracle:dbname';
my $user = 'xxxxx';
my $pass = 'xxxxxxxxxxx';
my $attr = {
FetchHashKeyName => 'NAME_lc',
RaiseError => 1,
PrintError => 0,
AutoCommit => 0,
ChopBlanks => 1,
};
my $rowcount = 11;
my $commitLevel = 10;
my $dbh = DBI->connect($dsn, $user, $pass, $attr);
my $queued_recs = $dbh->prepare("SELECT id from (SELECT id FROM queue
WHERE processed=\'F\' ORDER BY id ASC) where ROWNUM< $rowcount");
You could prepare your update statement here and avoid calling prepare
repeatedly.
my $going = 1;
while($going) {
$queued_recs->execute();
my @ids2process;
while ( my @ids = $queued_recs->fetchrow_array ) {
push(@ids2process, $ids[0]);
}
You know you are only going to get a list of ids back here so why bother
fetchrow_arraying it only to push onto @ids2process. Why not just
fetchall_arrayref in one go then loop over those.
if(!scalar(@ids2process)) {
sleep(5);
}
if(scalar(@ids2process)> 0 ) {
my $count=0;
foreach my $ids (@ids2process){
$count++;
my $ret = HandleIds($id);
next if($ret == -1);
We don't know what HandleIds does and it causes all remaining ids to be
ignored. This is probably where your problem is.
my $updated = '';
eval{
my $update_ids = $dbh->prepare("UPDATE
queue set processed = \'T
\' where id = $ids");
$updated = $update_ids->execute();
};
A good habit to get into is to use placeholders in your SQL - there are a lot
of good reasons for this documented all over the place:
prepare the update outside the loop with:
my $update_ids = $dbh->prepare(q/update queue set processed = ? where id = ?/);
then
$update_ids->execute('T', $ids);
if($@) { $log->error("Unable to update record for - id:
$id,
updated: $updated");}
else { $log->info("Updated record for - id: $id,
updated:
$updated");}
What if your code is wrong and you pass an id which does not exist in the table
- you do not know the update changed nothing. Check $updated contains 1.
if(($count % $commitLevel == 0) || ($count ==
scalar(@ids2process)))
{
my $commited = $dbh->commit;
$log->info("COMMIT at $count Ids, commited:
$commited");
}
}
There is something wrong with the above logic due to HandleIds() again. If your
select returns 10 rows but HandleIds returns -1 for the last id, next causes
the loop to end and your commit did not get called. Much better to do:
Personally I don't like turning off AutoCommit like this I prefer to do:
$dbh->begin_work;
do my work;
$dbh->commit;
i.e., put the commit outside the loop then you don't car how many ids were
processed, you just commit all the updates.
}else {
sleep(5);
}
}
Did you intend to sleep for 10s when there are no ids or 5?
Martin
--
Martin J. Evans
Easysoft Limited
http://www.easysoft.com