perl模块net mysql_Perl模块实例化DBI Forks“Mysql服务器已经消失”

我编写了一个perl程序,将csv中的记录解析为db.

该计划工作正常,但需要很长时间.所以我决定分叉主解析过程.

在用叉子进行一些争吵后,它现在运行良好,运行速度提高了约4倍.主要的解析方法是数据库密集型的.为了兴趣,对于每个被解析的记录,有以下db调用:

1 – 检查唯一生成的base62对于baseid映射表是唯一的

2 – 存档检查以查看记录是否已更改

3 – 将记录插入数据库

问题是,当解析器以分叉模式运行时,我开始得到“Mysql已经消失”的错误,所以经过多次摆弄后我想出了以下mysql配置:

#

# * 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服务器已经消失”.

奇怪的thinf是导致问题的模块涉及一个非常简单的SELECT查询,当前只有3条记录.直接作为测试运行(不是在解析器之后)它运行正常.

我尝试在解析器模块运行后添加4分钟的暂停 – 但是我得到了同样的错误.

我有一个主DBConnection.pm模型:

包DBConnection;

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的Module1.pm,它调用Module3.pm并且每个都实例化与DB的连接,如上所示(即在构造函数中)然后他们使用不同的连接到数据库或相同连接?

我想知道的是,如果脚本需要6个小时才能完成,如果对数据库连接的最高级别调用是超时低级别数据库连接,即使较低级别模块正在建立其“自己的”连接.

尝试找到问题非常令人沮丧,因为我只能在运行一个非常长的解析过程后重现错误.

很抱歉这个问题很长,感谢任何可以给我任何想法的人.

更新1:

这是实际的分叉部分:

my $fh = Tie::Handle::CSV->new( "$file", header => 1 );

while ( my $part = ) {

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();

}

据我了解,在分叉后调用数据库连接.

但是,正如我上面提到的,上面概述的分叉代码工作正常.它是下一个无法运行的模块,它从一个控制器模块运行,该控制器模块一次只运行一个工作模块(解析器就是其中之一) – 控制器模块不在其构造中或任何地方创建数据库连接其他.

更新2

我忘了提到我在解析器后面的’problem’模块中没有出现任何错误,如果我只解析少量文件而不是完整队列.

因此,几乎就像密集分叉解析和访问数据库一样,它在正常的非分叉进程刚刚结束一段时间后就不可用了.

当解析器运行完成Mysql状态时,我唯一注意到的是Threads_connected位于500周围并且不会减少一段时间.

解决方法:

这取决于你的程序的结构,这个问题并不清楚.

如果在fork之前创建数据库连接,Perl将为每个进程创建数据库连接对象的副本.如果两个进程尝试使用相同的数据库连接同时访问数据库,则可能会出现问题.

另一方面,如果在分叉后创建数据库连接,则每个模块都有自己的连接.这应该可以,但是如果Module x创建连接,则可能会出现超时问题,然后等待很长时间才能完成模块y中的进程,然后尝试使用该连接.

总之,这是你想要的:

>在叉子处没有任何打开的连接.子进程应该创建自己的连接.

>仅在您想要使用它之前打开连接.如果必须等待程序中有一个点,请在等待完成后打开连接.

标签:mysql,perl,fork,dbi

来源: https://codeday.me/bug/20190629/1327859.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值