为什么这个通过 ODBC 通过 DBI 连接到 MS SQL 服务器的 perl 程序会泄漏内存?

发布于 2024-10-21 04:29:54 字数 3131 浏览 2 评论 0原文

我在工作中维护了几个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨的味道风的声音 2024-10-28 04:29:54

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.

征﹌骨岁月お 2024-10-28 04:29:54

事实证明问题出在 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文