为什么这个通过 ODBC 通过 DBI 连接到 MS SQL 服务器的 perl 程序会泄漏内存?
我在工作中维护了几个 Perl 程序,这些程序在各种系统(WinXP、Win 2003、Linux)上运行良好多年。最近,我们在运行 SQL Server 2008 的 64 位 Windows 2008 Server 上为新客户端部署了它们。代码运行良好一段时间后就停止了。查看它,我发现我遇到了内存不足错误。为了追踪泄漏,我想出了以下示例程序,该程序在一两分钟内占用了大约 40 兆内存,并且还在不断增长。有什么想法吗?
use strict;
use warnings;
use DBI qw(:sql_types);
my $dbh = DBI->connect("DBI:ODBC:sample_db", "user", "pass");
my $query = $dbh->prepare("SELECT TOP 1 ID FROM TABLE");
while (1)
{
$query->execute();
while (my $row = $query->fetchrow_hashref() ){
print $row->{ID} . "\n";
}
$query->finish();
}
我正在运行 Strawberry Perl 5.12.2,但也能够在 5.10 版本的机器上重现这一点。
C:>perl -V
Summary of my perl5 (revision 5 version 12 subversion 2) configuration:
Platform:
osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
uname='Win32 strawberryperl 5.12.2.0 #1 Fri Nov 5 05:17:27 2010 i386'
config_args='undef'
hint=recommended, useposix=true, d_sigaction=undef
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='gcc', ccflags =' -s -O2 -DWIN32 -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -
DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields -
DPERL_MSVC`enter code here`RT_READFIX',
optimize='-s -O2',
cppflags='-DWIN32'
ccversion='', gccversion='4.4.3', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='long long', lseek
size=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='g++', ldflags ='-s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\li
b"'
libpth=C:\strawberry\c\lib C:\strawberry\c\i686-w64-mingw32\lib
libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32
-lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion
-lodbc32 -lodbccp32 -lcomctl32
perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladva
pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lver
sion -lodbc32 -lodbccp32 -lcomctl32
libc=, so=dll, useshrplib=true, libperl=libperl512.a
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags='-mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\st
rawberry\c\lib"'
Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV
PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS
USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF
USE_SITECUSTOMIZE
Built under MSWin32
Compiled at Nov 5 2010 08:39:08
@INC:
C:/strawberry/perl/site/lib
C:/strawberry/perl/vendor/lib
C:/strawberry/perl/lib
.
I have several Perl programs that I maintain at work that have been running fine for years on various systems (WinXP, Win 2003, Linux). Recently we have deployed them for a new client on a 64 bit Windows 2008 Server running SQL Server 2008. The code ran fine for a bit then it stopped. Looking into it I saw that I was getting out-of-memory errors. Attempting to track down the leak I came up with the following sample program that withing a min or two claims about 40megs of memory and just keeps growing. Any ideas?
use strict;
use warnings;
use DBI qw(:sql_types);
my $dbh = DBI->connect("DBI:ODBC:sample_db", "user", "pass");
my $query = $dbh->prepare("SELECT TOP 1 ID FROM TABLE");
while (1)
{
$query->execute();
while (my $row = $query->fetchrow_hashref() ){
print $row->{ID} . "\n";
}
$query->finish();
}
I'm running strawberry perl 5.12.2 but have been able to reproduce this on this box with the 5.10 build as well.
C:>perl -V
Summary of my perl5 (revision 5 version 12 subversion 2) configuration:
Platform:
osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
uname='Win32 strawberryperl 5.12.2.0 #1 Fri Nov 5 05:17:27 2010 i386'
config_args='undef'
hint=recommended, useposix=true, d_sigaction=undef
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='gcc', ccflags =' -s -O2 -DWIN32 -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -
DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields -
DPERL_MSVC`enter code here`RT_READFIX',
optimize='-s -O2',
cppflags='-DWIN32'
ccversion='', gccversion='4.4.3', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='long long', lseek
size=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='g++', ldflags ='-s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\li
b"'
libpth=C:\strawberry\c\lib C:\strawberry\c\i686-w64-mingw32\lib
libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32
-lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion
-lodbc32 -lodbccp32 -lcomctl32
perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladva
pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lver
sion -lodbc32 -lodbccp32 -lcomctl32
libc=, so=dll, useshrplib=true, libperl=libperl512.a
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags='-mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\st
rawberry\c\lib"'
Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV
PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS
USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF
USE_SITECUSTOMIZE
Built under MSWin32
Compiled at Nov 5 2010 08:39:08
@INC:
C:/strawberry/perl/site/lib
C:/strawberry/perl/vendor/lib
C:/strawberry/perl/lib
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1.24_2 中引入了一个泄漏,直到 1.26_3 才修复。来自更改文件:
=head2 DBD::ODBC 1.26_3 中的更改 2010 年 11 月 18 日
修复了 rt 63108。1.24_2 中对列绑定的更改未更改
完成并导致绑定列在每次执行时反弹
浪费时间并泄漏内存。发现、诊断并提出修复建议
史蒂夫·本特利。
当发生类似情况时,检查您使用的模块的变更日志总是值得的。
There was a leak introduced in 1.24_2 which was not fixed until 1.26_3. From the changes file:
=head2 Changes in DBD::ODBC 1.26_3 November 18, 2010
Fixed rt 63108. The change to column binding in 1.24_2 was not
complete and causes bound columns to be rebound on each execute
wasting time and leaking memory. Found, diagnosed and proposed fix
by Steve Bentley.
It is always worth checking the changelog for modules you use when something like this happens.
事实证明问题出在 DBD::ODBC 模块上。我有一个稍微过时的版本(1.26,我相信忘记注意到它)。使用 cpan 升级到 1.29 解决了这个问题。
Turns out the problems was with the DBD::ODBC module. I had a slightly out of date version (1.26 I believe forgot to take note of it). Using cpan to upgrade to 1.29 took care of the problem.