4

csv から db にレコードを解析する perl プログラムを作成しました。

プログラムは問題なく動作しましたが、時間がかかりました。そこで、メインの解析プロセスをフォークすることにしました。

fork と少し格闘した後、正常に動作し、約 4 倍速く実行されます。主な解析方法は、かなりデータベースを集中的に使用します。便宜上、解析されるレコードごとに、次の db 呼び出しがあります。

1 - 一意に生成された base62 が baseid マップ テーブルに対して一意であることがチェックされます 2 - レコードが変更されたかどうかを確認するためにアーカイブ チェックが行われます 3 - レコードがデータベースに挿入されます

問題は、パーサーが fork モードで実行されている間に「Mysql has gone away」エラーが発生し始めたことです。

#
# * Fine Tuning
#
key_buffer              = 10000M
max_allowed_packet      = 10000M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
max_connections        = 10000
table_cache            = 64
thread_concurrency     = 32
wait_timeout           = 15
tmp_table_size  = 1024M

query_cache_limit       = 2M
#query_cache_size        = 100M
query_cache_size = 0
query_cache_type = 0

パーサーの実行中の問題は修正されたようですが、メインのパーサーの後に次のモジュールが実行されると、「Mysql server has gone away」というメッセージが表示されます。

奇妙な点は、現在 3 つのレコードしかないテーブルに対する非常に単純な SELECT クエリが問題を引き起こしているモジュールです。(パーサーの後ではなく) テストとして直接実行すると、問題なく動作します。

パーサー モジュールの実行後に 4 分間の一時停止を追加しようとしましたが、同じエラーが発生します。

これを含むメインの DBConnection.pm モデルがあります。

use DBI;
use PXConfig;

sub new {
    my $class    = shift;
    ## MYSQL Connection
    my $config = new PXConfig();
    my $host     = $config->val('database', 'host');
    my $database = $config->val('database', 'db');
    my $user     = $config->val('database', 'user');
    my $pw       = $config->val('database', 'password');
    my $dsn      = "DBI:mysql:database=$database;host=$host;"; 
    my $connect2 = DBI->connect( $dsn, $user, $pw,  );
    $connect2->{mysql_auto_reconnect} = 1;
    $connect2->{RaiseError} = 1;
    $connect2->{PrintError} = 1;
    $connect2->{ShowErrorStatement} = 1;
    $connect2->{InactiveDestroy} = 1;

    my $self     = {
        connect => $connect2,
    };
    bless $self, $class;
    return $self;
}

次に、フォークされたパーサー モジュールを含むすべてのモジュールが、次を使用して DB への接続を開きます。

package Example;

use DBConnection;

sub new {
    my $class    = shift;
    my $db       = new DBConnection;
    my $connect2 = $db->connect();
    my $self     = {
        connect2 => $connect2,
    };
    bless $self, $class;
    return $self;
}

問題は、Module3.pm を呼び出す Module2.pm を呼び出す Module1.pm があり、それぞれが上記のように (つまり、コンストラクターで) DB との接続をインスタンス化する場合、データベースへの異なる接続を使用するか、同じ接続を使用するかです。繋がり?

私が疑問に思ったのは、下位レベルのモジュールが「独自の」接続を確立しているにもかかわらず、db 接続へのトップレベルの呼び出しが下位レベルの db 接続をタイムアウトしている場合、スクリプトが完了するまでに 6 時間かかるかどうかです。

非常に長い解析プロセスを実行した後にしかエラーを再現できないため、問題を見つけようとするのは非常にイライラします。

長い質問で申し訳ありませんが、私にアイ​​デアを提供できる人に事前に感謝します。


更新 1:

実際の分岐部分は次のとおりです。

my $fh = Tie::Handle::CSV->new( "$file", header => 1 );
while ( my $part = <$fh> ) {
    if ( $children == $max_threads ) {
        $pid = wait();
        $children--;
    }
    if ( defined( $pid = fork ) ) {
        if ($pid) {
            $children++;
        } else {
            $cfptu = new ThreadedUnit();
            $cfptu->parseThreadedUnit($part, $group_id, $feed_id);
        }
    }
}

そして、ThreadedUnit:

package ThreadedUnit;

use CollisionChecker;
use ArchiveController;
use Filters;
use Try::Tiny;
use MysqlLogger;

sub new {
    my $class    = shift;
    my $db       = new DBConnection;
    my $connect2 = $db->connect();
    my $self     = {
        connect2 => $connect2,
    };
    bless $self, $class;
    return $self;
}

sub parseThreadedUnit {
    my ( $self, $part, $group_id, $feed_id ) = @_;
    my $connect2 = $self->{connect2};

    ## Parsing stuff

    ## DB Update in try -> catch
    exit();
}

私が理解しているように、分岐後にDB接続が呼び出されています。

しかし、上で述べたように、上で概説したフォークされたコードは問題なく動作します。各ワーカーモジュールを一度に1つずつ実行するコントローラーモジュールから実行されているのは、機能しない次のモジュールです(パーサーはそれらの1つです)-コントローラーモジュールは、その構造またはどこにもDB接続を作成しませんそうしないと。


更新 2

完全なキューではなく少数のファイルのみを解析する場合、パーサーに続く「問題」モジュールでエラーが発生しないことを忘れていました。

そのため、フォークされた集中的な解析と DB へのアクセスにより、DB が終了した直後に通常のフォークされていないプロセスで利用できなくなるかのようです。

パーサーの実行が Mysql ステータスで終了したときに気付いた唯一のことは、Threads_connected が 500 前後にあり、しばらくの間減少しないことです。

4

2 に答える 2

1

dan1111 の回答を読んでください。ただし、接続してから分岐していると思われます。子プロセスが完了すると、DBI 接続ハンドルは範囲外になり、閉じられます。dan1111 が言うように、彼が言ったすべての理由から、あなたは子供の中でより良いつながりを持っています。DBI のInactiveDestroyAutoInactiveDestroyについて読んでください。何が起こっているのかを理解するのに役立ちます。

于 2013-04-12T08:39:36.003 に答える