2012-09-01 55 views
5

我有一个很大的事务,包括从数据库A获取大量数据,对这些数据做一些操作,然后将操纵的数据插入到数据库B中。我只有权限在数据库A中进行选择,但是我可以在数据库B中创建表和插入/更新等。用perl处理长时间运行的大型事务dbi

操作和插入部分用Perl编写,并且已经在使用从其他数据源将数据加载到数据库B,所以需要的是从数据库A获取必要的数据并使用它来初始化perl类。

我该如何解决这个问题,以便在操作或插入过程中发生错误时,我可以轻松追踪并拾取错误发生的位置(数据库断开连接,由于无效值而导致类初始化问题,硬盘失败等......)?一次做交易似乎不是一个好的选择,因为数据库A的数据量意味着数据处理和插入到数据库B至少需要一天或两天的时间。

来自数据库A的数据可以使用唯一密钥分组到大约1000个组中,每个密钥包含1000个行。我认为我可以做的一种方式是编写一个脚本来完成每个组的提交,这意味着我必须跟踪哪个组已经被插入到数据库B中。唯一可以考虑的方式是跟踪哪些组的进度被处理与否是在日志文件中还是在数据库B中的表中。第二种我认为可以工作的方式是转储所有必要的字段,用于将用于操作和插入的类加载到平面文件中,读取文件以初始化类和插入数据库B.这也意味着我要做一些日志记录,但应该缩小到平面文件中的确切行,如果发生任何错误。该脚本将是这个样子:

use strict; 
use warnings; 
use DBI; 

#connect to database A 
my $dbh = DBI->connect('dbi:oracle:my_db', $user, $password, { RaiseError => 1, AutoCommit => 0 }); 

#statement to get data based on group unique key 
my $sth = $dbh->prepare($my_sql); 

my @groups; #I have a list of this already 

open my $fh, '>>', 'my_logfile' or die "can't open logfile $!"; 

eval { 
    foreach my $g (@groups){ 
     #subroutine to check if group has already been processed, either from log file or from database table 
     next if is_processed($g); 

     $sth->execute($g); 
     my $data = $sth->fetchall_arrayref; 

     #manipulate $data, then use it to load perl classes for insertion into database B 
     #. 
     #. 
     #. 
    } 
    print $fh "$g\n"; 
}; 
if ([email protected]){ 
    $dbh->rollback; 
    die "something wrong...rollback"; 
} 

因此,如果不发生任何错误,我可以再次运行此脚本,它应该跳过已经处理组或行,然后继续。

这两种方法只是在同一主题上的变体,都需要回到我一直跟踪进度的地方(在表或文件中),跳过那些已经提交到数据库B并处理剩余的数据。

我相信有这样做的更好的方法,但我正在努力思考其他解决方案。是否有另一种处理数据库之间的大型事务的方法,需要在从一个数据中取出数据并插入另一个数据之间进行数据操作这个过程并不需要全部用Perl,只要我可以重复使用perl类来操作数据并将其插入数据库即可。

回答

2

很抱歉这么说,但我真的没有看到你如何通过捷径解决这个问题。对我来说,它听起来就像你虽然关于最合理的方式:

  • 保存在每一步
  • 在一些临时表/文件中的状态(我会考虑“的perldoc -f领带”,或源码)正确
  • 处理错误TryCatch.pm,EVAL或任何你喜欢的
  • 正常登录你的错误,即结构化的日志,你可以阅读
  • 添加一些“恢复”标志,以你的脚本读取以前的日志和数据,并尝试再次

This i这可能与你一直在想的一样,但正如我所说的,我认为没有一种“正确”的方式来处理你的问题。

+0

感谢您的反馈意见,我只是想看看是否有其他选择,以防我一直在思考过于狭隘,错过了更简单/明显的事情 – 1stdayonthejob

相关问题