Perl模块实例化DBI Forks“Mysql服务器已经消失”
我编写了一个perl程序,将csv中的记录解析为db.
该计划工作正常,但需要很长时间.所以我决定分叉主解析过程. 在用叉子进行一些争吵后,它现在运行良好,运行速度提高了约4倍.主要的解析方法是数据库密集型的.为了兴趣,对于每个被解析的记录,有以下db调用: 1 – 检查唯一生成的base62对于baseid映射表是唯一的 问题是,当解析器以分叉模式运行时,我开始得到“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模型: 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,$class; return $self; } 问题是我是否有调用Module3.pm的Module1.pm,它调用Module3.pm并且每个都实例化与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,$class; return $self; } sub parseThreadedUnit { my ( $self,$part,$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中的进程,然后尝试使用该连接. 总之,这是你想要的: >在叉子处没有任何打开的连接.子进程应该创建自己的连接.>仅在您想要使用它之前打开连接.如果必须等待程序中有一个点,请在等待完成后打开连接. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |