- 论坛徽章:
- 0
|
本帖最后由 jjqing 于 2011-08-23 23:59 编辑
今天在windowsXP客户端上面使用dbd::oracle对数据库进行大批量查询时发现,perl.exe对内存的使用是不断上涨,直到2G时,报out of memory然后退出。
为了测试这个问题,我用了一个简单的查询来进行模拟,使用了三种方法来使用DBD::Oracle,由于简单查询不可能把内存使用达到2G,因此,我只是想说明,在这三种方法中,perl.exe的内存都是在不断上涨的,想请各位指导一下,如何释放内存,如何控制对内存的使用,谢谢!
测试方法:
一、使用标准的DBD::Oracle用法,即只connect()一次,然后对每个语句做prepare,再execute,再fetch,再finish,最后在程序退出的时候执行disconnect():
- use strict;
- use warnings;
- use diagnostics;
- use Smart::Comments '###';
- use DBI;
- use DBD::Oracle qw(:ora_session_modes);
- my $user = "system";
- my $passwd = "oracle";
- my $tns = "ORCL_DEV";
- my $dsn = "dbi:Oracle:$tns";
- my $dbh = DBI->connect( $dsn, $user, $passwd, {RaiseError => 0} );
- for ( my $i = 1; $i < 2000 ; $i++ ) {
- login_once($i);
- }
- sub login_once {
- my $i = shift;
- print "do sql test $i\n";
- my $sql = "SELECT count(*) total_user FROM dba_users";
- my $sth = $dbh->prepare( $sql );
- $sth->execute( );
- my @rows = $sth->fetchrow_array;
- print "\t total user is $rows[0] \n";
- $sth->finish();
- }
- sleep 60000;
- $dbh->disconnect();
复制代码 二、对方法一做一处修改,在循环过程中不执行finish()操作:
- use strict;
- use warnings;
- use diagnostics;
- use Smart::Comments '###';
- use DBI;
- use DBD::Oracle qw(:ora_session_modes);
- my $user = "system";
- my $passwd = "oracle";
- my $tns = "ORCL_DEV";
- my $dsn = "dbi:Oracle:$tns";
- my $dbh = DBI->connect( $dsn, $user, $passwd, {RaiseError => 0} );
- for ( my $i = 1; $i < 2000 ; $i++ ) {
- login_once($i);
- }
- sub login_once {
- my $i = shift;
- print "do sql test $i\n";
- my $sql = "SELECT count(*) total_user FROM dba_users";
- my $sth = $dbh->prepare( $sql );
- $sth->execute( );
- my @rows = $sth->fetchrow_array;
- print "\t total user is $rows[0] \n";
- #$sth->finish();
- }
- sleep 60000;
- $dbh->disconnect();
复制代码 三、每执行一个sql,进行一次connect(),然后依次是prepare/execute/fetch/finish/disconnect():
- use strict;
- use warnings;
- use diagnostics;
- use Smart::Comments '###';
- use DBI;
- use DBD::Oracle qw(:ora_session_modes);
- my $user = "system";
- my $passwd = "oracle";
- my $tns = "ORCL_DEV";
- my $dsn = "dbi:Oracle:$tns";
- for ( my $i = 1; $i < 2000 ; $i++ ) {
- login_everyonce($i);
- }
- sleep 60000;
- sub login_everyonce {
- my $i = shift;
- print "do sql test $i\n";
- my $dbh = DBI->connect( $dsn, $user, $passwd, {RaiseError => 0} );
- my $sql = "SELECT count(*) total_user FROM dba_users";
- my $sth = $dbh->prepare( $sql );
- $sth->execute( );
- my @rows = $sth->fetchrow_array;
- print "\t total user is $rows[0] \n";
- $sth->finish();
- $dbh->disconnect();
- }
复制代码 通过以上三种方法,我进行了2000次循环,测试结果如下:
脚本名称 进程ID 使用内存 CPU时间
dbd1.pl 5568 17,840 K 00:00:02
dbd2.pl 6404 17,840 K 00:00:02
dbd3.pl 4192 18,716 k 00:00:45
测试结果让我感到奇怪:
方法一和方法二,对windows客户端来说,使用的内存数量完全一样,没有差别。
对于方法三,我原以为它是最省内存的,结果它使用的内存是最多的。
原因不明!但是看起来,内存上涨,好像不是DBD::Oracle的错!那是哪里错了呢?
请各位帮忙分析一下,为什么一条小小的select count(*) from dba_usrs,执行了2000次之后,会占用17M的内存呢?是哪个变量占用了这些内存?
并且它对内存的使用,是随着每个循环,而不断加大的,从来没有释放过。
请问,有办法释放或控制内存么?因为这个测试里面只是很小的查询,如果是很大的查询,几十个循环下来,perl.exe进程立即超过2G内存了。。。
谢谢各位!如果我还有描述得不清楚的地方,请各位多多指正,我会立即补充! |
|