问题 Perl连接池


现在我们有一个大型的perl应用程序,它使用原始DBI连接到MySQL并执行SQL语句。它每次都创建一个连接并终止。开始接近mysql的连接限制(一次200)

看起来像 DBIx ::连接 支持应用程序层连接池。

有没有人有任何经验 DBIx::Connection?。连接池是否还有其他注意事项?

我也看到了 mod_dbd 这是一个看起来像处理连接池的Apache mod。 http://httpd.apache.org/docs/2.1/mod/mod_dbd.html 


1332
2017-07-16 17:55


起源

我使用DBIx :: Connector(DBIx :: Class在内部使用)并且它很棒......我将这些连接与Moose对象包装器汇集在一起​​,如果连接参数相同,则会将现有对象实例交给它。推出自己的并不难。 - Ether
@Ether - 值得一个答案,恕我直言 - DVK
@DVK:好的,我通过答案对此进行了扩展...... - Ether
@Ether,你的评论应该是一个答案,以便它可以被接受,因为它正是OP所要求的。 - mpeters
什么是 raw DBI,它有什么不同 DBI? - vol7ron


答案:


我对DBIx :: Connection没有任何经验,但是我使用了 DBIx ::连接器 (基本上是DBIx :: Class在内部使用的内容,但内联)并且很棒......

我将这些连接与Moose对象包装器集合在一起,如果连接参数相同,则会将现有对象实例交给它(对于任何底层数据库对象,这都是相同的):

package MyApp::Factory::DatabaseConnection;
use strict;
use warnings;

use Moose;

# table of database name -> connection objects
has connection_pool => (
    is => 'ro', isa => 'HashRef[DBIx::Connector]',
    traits  => ['Hash'],
    handles => {
        has_pooled_connection => 'exists',
        get_pooled_connection => 'get',
        save_pooled_connection => 'set',
    },
    default => sub { {} },
);

sub get_connection
{
    my ($self, %options) = @_;

    # some application-specific parsing of %options here...

    my $obj;
    if ($options{reuse})
    {
        # extract the last-allocated connection for this database and pass it
        # back, if there is one.
        $obj = $self->get_pooled_connection($options{database});
    }

    if (not $obj or not $obj->connected)
    {
        # look up connection info based on requested database name
        my ($dsn, $username, $password) = $self->get_connection_info($options{database});
        $obj = DBIx::Connector->new($dsn, $username, $password);

        return unless $obj;

        # Save this connection for later reuse, possibly replacing an earlier
        # saved connection (this latest one has the highest chance of being in
        # the same pid as a subsequent request).
        $self->save_pooled_connection($options{database}, $obj) unless $options{nosave};
    }

    return $obj;
}

8
2017-07-16 20:50



请你分享整个代码,请提供使用Rose :: DB处理程序实现的解决方案 - Sethu
@Sethu即整个代码。我不建议在任何情况下使用Rose :: DB。 - Ether
get_connection_info是预定义的函数吗?如果不善意也分享这个功能。 - Sethu
我已经尝试过ResourcePool Perl模块用于数据库池。对于每个HTTP请求,它都会创建新池而不是重用它。在下面找到我的代码 - Sethu
@Sethu,你应该写 get_connection_info 您自己,在给定数据库名称的情况下提供适当的凭据。 - Ether


只是确保:你知道 DBI->connect_cached(), 对?这是替代品 connect() 在可能的情况下,在perl脚本的生命周期中重用dbh。也许你的问题可以通过添加7个字符来解决:)

而且,MySQL的连接相对便宜。在你的DB上运行 max_connections=1000 或更多本身不会导致问题。 (如果您的客户要求的工作量超出您的数据库所能处理的范围,那么这是一个更严重的问题,一个更低的问题 max_connections 可能会推迟,但当然不能解决。)


5
2017-08-14 17:15



我认为免费版的MySql只支持200个连接吗? - bonez
MySQL的免费版本没有任何削弱。 (除非你算上GPL,哈哈。)即使是大而写得不好的应用程序也不需要超过几千个,但你可以设置 MAX_CONNECTIONS 如果您有内存和文件描述符,请尽可能高。 - Jamie McCarthy
MySQL没有“付费”版本。这都是GPL。最好的情况是,Oracle可能会有一份您可以支付的支持合同,但该软件本身是完全免费且未开发的。 - Brendan Byrd