5

データベース A から大量のデータを取得し、このデータを操作してから、操作したデータをデータベース B に挿入するという大規模なトランザクションがあります。データベース A で選択する権限しかありませんが、テーブルを作成してデータベースBに挿入/更新など。

操作と挿入部分は perl で記述されており、他のデータ ソースからデータベース B にデータをロードするために既に使用されているため、データベース A から必要なデータを取得し、それを使用して perl クラスを初期化するだけです。

操作または挿入手順中にエラーが発生した場合 (データベースの切断、無効な値によるクラスの初期化の問題、ハードディスクの障害など) に、エラーが発生した場所を簡単に追跡して取得できるようにするにはどうすればよいでしょうか。 .)? データベース A からのデータの量は、データの操作とデータベース B への挿入に少なくとも 1 日か 2 日かかることを意味するため、一度にトランザクションを実行することは適切なオプションとは思えません。

データベース A のデータは、一意のキーを使用して約 1000 のグループにグループ化できます。各キーにはそれぞれ数千行が含まれます。私ができると思った 1 つの方法は、グループごとにコミットを行うスクリプトを作成することです。つまり、どのグループがデータベース B に既に挿入されているかを追跡する必要があります。処理されたかどうかは、ログ ファイルまたはデータベース B のテーブルにあります。2 つ目の方法は、クラスをロードして操作および挿入するために必要なすべてのフィールドをダンプし、ファイルを読み取って初期化することです。これは、ログを記録する必要があることも意味しますが、エラーが発生した場合はフラットファイル内の正確な行に絞り込む必要があります。スクリプトは次のようになります。

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 ($@){
   $dbh->rollback;
   die "something wrong...rollback";
}

したがって、エラーが発生した場合は、このスクリプトを再度実行するだけで、処理済みのグループまたは行をスキップして続行することができます。

これらの方法はどちらも同じテーマの単なるバリエーションであり、どちらも進行状況を追跡していた場所 (テーブルまたはファイル) に戻り、データベース B にコミットされたものをスキップして残りのデータを処理する必要があります。

これを行うためのより良い方法があると確信していますが、他の解決策を考えるのに苦労しています。あるデータベースからデータを取得して別のデータベースに挿入する間にデータ操作を必要とする、データベース間の大規模なトランザクションを処理する別の方法はありますか? データを操作してデータベースに挿入するために perl クラスを再利用できる限り、プロセスはすべて Perl である必要はありません。

4

1 に答える 1

2

申し訳ありませんが、ショートカットを使用してこの問題を解決する方法が本当にわかりません。私には、あなたが最も合理的な方法について考えたことがあるように思えます。

  • 各ステップで、状態をいくつかの一時テーブル/ファイルに保存します (「perldoc -f tie」または sqlite を調べます)。
  • エラーを適切に処理する TryCatch.pm、eval、または好みのもの
  • エラーを適切に記録します。つまり、読み込める構造化されたログ
  • 以前のログとデータを読み取って再試行する「再開」フラグをスクリプトに追加します

これはおそらくあなたが考えてきた線に沿っていますが、私が言ったように、あなたの問題を処理するための一般的な「正しい」方法はないと思います.

于 2012-09-01T16:37:21.247 に答える