DBD / DBI:如果对程序进行了分叉,则会崩溃

奥莱·丹吉(Ole Tange)

如果未设置$ crash参数,则以下程序可以工作:

$ perl example mysql://:tange@/tange/mytable
dburl mysql://:tange@/tange/mytable
databasedriver mysql user  password tange host  port  database tange table mytable query 
run DROP TABLE IF EXISTS mytable;
run CREATE TABLE mytable
                (Seq INT,
                 Exitval INT
                 );
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);

如果设置了$ crash,则bzip2通过open3运行,数据通过派生进程发送,这会使DBD / DBI崩溃:

$ perl example mysql://:tange@/tange/mytable 1
dburl mysql://:tange@/tange/mytable
databasedriver mysql user  password tange host  port  database tange table mytable query 
run DROP TABLE IF EXISTS mytable;
run CREATE TABLE mytable
                (Seq INT,
                 Exitval INT
                 );
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
Orig:
As bzip2:BZh9rE8P�
1
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
DBD::mysql::st execute failed: MySQL server has gone away at example line 157.
DBD::mysql::st execute failed: MySQL server has gone away at example line 157.

如果使用Postgresql,也是如此:

$ perl example pg:////mytable 
dburl pg:////mytable
databasedriver pg user  password  host  port  database  table mytable query 
run DROP TABLE IF EXISTS mytable;
run CREATE TABLE mytable
                (Seq INT,
                 Exitval INT
                 );
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);

并设置了$ crash:

$ perl example pg:////mytable 1
dburl pg:////mytable
databasedriver pg user  password  host  port  database  table mytable query 
run DROP TABLE IF EXISTS mytable;
run CREATE TABLE mytable
                (Seq INT,
                 Exitval INT
                 );
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
Orig:
As bzip2:BZh9rE8P�
1
run INSERT INTO mytable (Seq,Exitval) VALUES (?,?);
DBD::Pg::st execute failed: server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request. at example line 157.
DBD::Pg::st execute failed: server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request. at example line 157.

为什么?有解决方法吗?

对我来说,open3和fork与DBD / DBI完全无关。


#!/usr/bin/perl

use IPC::Open3;

my $sql = SQL->new(shift);
my $crash = shift;
$Global::debug = "all";
$sql->create_table();
$sql->insert_records(2);
$crash and print length string_zip("abc"),"\n";
$sql->insert_records(3);

sub string_zip {
    # Pipe string through 'cmd'
    my $cmd = shift;
    my($zipin_fh, $zipout_fh,@base64);
    ::open3($zipin_fh,$zipout_fh,">&STDERR","bzip2 -9");
    if(fork) {
    close $zipin_fh;
    @base64 = <$zipout_fh>;
    close $zipout_fh;
    } else {
    close $zipout_fh;
    print $zipin_fh @_;
    close $zipin_fh;
    exit;
    }
    ::debug("zip","Orig:@_\nAs bzip2:@base64\n");
    return @base64;
}

sub undef_if_empty {
    if(defined($_[0]) and $_[0] eq "") {
    return undef;
    }
    return $_[0];
}

sub debug {
    # Uses:
    #   $Global::debug
    #   %Global::fd
    # Returns: N/A
    print @_[1..$#_];
}

package SQL;

sub new {
    my $class = shift;
    my $dburl = shift;
    $Global::use{"DBI"} ||= eval "use DBI; 1;";
    my %options = parse_dburl($dburl);
    my %driveralias = ("sqlite" => "SQLite",
               "sqlite3" => "SQLite",
               "pg" => "Pg",
               "postgres" => "Pg",
               "postgresql" => "Pg");
    my $driver = $driveralias{$options{'databasedriver'}} || $options{'databasedriver'};
    my $database = $options{'database'};
    my $host = $options{'host'} ? ";host=".$options{'host'} : "";
    my $port = $options{'port'} ? ";port=".$options{'port'} : "";
    my $dsn = "DBI:$driver:dbname=$database$host$port";
    my $userid = $options{'user'};
    my $password = $options{'password'};;
    my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1 })
    or die $DBI::errstr;
    return bless {
    'dbh' => $dbh,
    'max_number_of_args' => undef,
    'table' => $options{'table'},
    }, ref($class) || $class;
}

sub parse_dburl {
    my $url = shift;
    my %options = ();
    # sql:mysql://[[user][:password]@][host][:port]/[database[/table][?sql query]]

    if($url=~m!(?:sql:)? # You can prefix with 'sql:'
               ((?:oracle|ora|mysql|pg|postgres|postgresql)(?:s|ssl|)|
                 (?:sqlite|sqlite2|sqlite3)):// # Databasedriver ($1)
               (?:
                ([^:@/][^:@]*|) # Username ($2)
                (?:
                 :([^@]*) # Password ($3)
                )?
               @)?
               ([^:/]*)? # Hostname ($4)
               (?:
                :
                ([^/]*)? # Port ($5)
               )?
               (?:
                /
                ([^/?]*)? # Database ($6)
               )?
               (?:
                /
                ([^?]*)? # Table ($7)
               )?
               (?:
                \?
                (.*)? # Query ($8)
               )?
              !ix) {
    $options{databasedriver} = ::undef_if_empty(lc(uri_unescape($1)));
    $options{user} = ::undef_if_empty(uri_unescape($2));
    $options{password} = ::undef_if_empty(uri_unescape($3));
    $options{host} = ::undef_if_empty(uri_unescape($4));
    $options{port} = ::undef_if_empty(uri_unescape($5));
    $options{database} = ::undef_if_empty(uri_unescape($6));
    $options{table} = ::undef_if_empty(uri_unescape($7));
    $options{query} = ::undef_if_empty(uri_unescape($8));
    ::debug("sql","dburl $url\n");
    ::debug("sql","databasedriver ",$options{databasedriver}, " user ", $options{user},
          " password ", $options{password}, " host ", $options{host},
          " port ", $options{port}, " database ", $options{database},
          " table ",$options{table}," query ",$options{query}, "\n");

    } else {
    ::error("$url is not a valid DBURL");
    exit 255;
    }
    return %options;
}

sub uri_unescape {
    # Copied from http://cpansearch.perl.org/src/GAAS/URI-1.55/URI/Escape.pm
    # to avoid depending on URI::Escape
    # This section is (C) Gisle Aas.
    # Note from RFC1630:  "Sequences which start with a percent sign
    # but are not followed by two hexadecimal characters are reserved
    # for future extension"
    my $str = shift;
    if (@_ && wantarray) {
    # not executed for the common case of a single argument
    my @str = ($str, @_);  # need to copy
    foreach (@str) {
        s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
    }
    return @str;
    }
    $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if defined $str;
    $str;
}

sub run {
    my $self = shift;
    my $stmt = shift;
    my $dbh = $self->{'dbh'};
    ::debug("sql","run $stmt\n");
    # Execute with the rest of the args - if any
    my $rv;
    my $sth;
    $sth = $dbh->prepare($stmt);
    $rv = $sth->execute(@_);
    return $sth;
}

sub table {
    my $self = shift;
    return $self->{'table'};
}

sub create_table {
    my $self = shift;
    my $table = $self->table();
    $self->run(qq(DROP TABLE IF EXISTS $table;));
    $self->run(qq{CREATE TABLE $table
        (Seq INT,
         Exitval INT
         }.
           qq{);});
}

sub insert_records {
    my $self = shift;
    my $seq = shift;
    my $record_ref = shift;
    my $table = $self->table();
    $self->run("INSERT INTO $table (Seq,Exitval) ".
           "VALUES (?,?);", $seq, -1000);
}
丹尼尔·特鲁斯(Daniel Truth)

当子进程或父进程退出时,它将关闭其数据库句柄和关联的套接字,并且在服务器端,相应的后端退出。

从那时起,如果另一个(仍然存在的)客户端进程尝试使用数据库句柄,则由于MySQL服务器已消失或postgres服务器意外关闭了连接,发送查询将失败这些消息似乎很正确地描述了发生了什么。

主要解决方法是在进程DBI->connect()之后调用fork而不以任何方式共享数据库句柄。

如果数据库活动仅限于父级,则可以AutoInactiveDestroy尽早在db句柄上进行设置(因为DBI 1.614)。这应该InactiveDestroy在孩子中自动设置,并解决问题。请参阅InactiveDestroyDBI文档:

对于数据库句柄,此属性不会禁用对断开连接方法的显式调用,只有在将句柄仍标记为“活动”的情况下,才会发生来自DESTROY的隐式调用。

该属性是专门为在“分叉”子进程的Unix应用程序中使用而设计的。对于某些驱动程序,当子进程退出时,继承句柄的破坏会导致父进程中的相应句柄停止工作。

父进程或子进程(但不能同时)都应在其所有共享句柄上将InactiveDestroy设置为true。替代地,并且优选地,可以在连接时在父节点中设置“ AutoInactiveDestroy”。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用DBI / DBD :: PG的Postgresql框类型的占位符

来自分类Dev

无法编译DBD-Oracle-1.74 | 找不到DBI.pm

来自分类Dev

Ubuntu 上的 Apache 2.4:“无法加载驱动程序文件 apr_dbd_oracle.so”

来自分类Dev

安装DBD :: Oracle时出错

来自分类Dev

Apache2 Auth dbd-数据库中的md5哈希密码,但是apache将其与原始密码进行比较

来自分类Dev

在Mac上安装perl DBD:Pg

来自分类Dev

DBD :: ODBC与Win32 :: odbc

来自分类Dev

Linux:如何安装DBD :: Pg模块?

来自分类Dev

DBD :: SQLite插入多行的最快方法

来自分类Dev

安装perl-DBD-mysql时出错

来自分类Dev

Linux:如何安装DBD :: Pg模块?

来自分类Dev

Perl:DBD :: ODBC :: st执行失败

来自分类Dev

仅保存如果进行了更改

来自分类Dev

尽管进行了错误处理,Windows 8.1 XAML应用程序仍然崩溃

来自分类Dev

Perl和DBD :: Oracle-可提取多少行?RowsInCache?

来自分类Dev

How to install the perl module DBD::Sybase on Unix (Mac OSX)?

来自分类Dev

DBD :: mysql :: st执行失败:MySQL服务器消失了

来自分类Dev

Perl和DBD :: Oracle-可提取多少行?RowsInCache?

来自分类Dev

在配置投影时,Vertica DBD是否考虑内部查询?

来自分类Dev

DBD :: Oracle :: st执行失败:系统生成的消息

来自分类Dev

Perl install_driver(Oracle)失败:-无法为模块DBD :: Oracle Win64加载'../DBD/Oracle/Oracle.dll'

来自分类Dev

DES程序进行了很多回合。

来自分类Dev

尝试创建python程序,但使用def进行了简化

来自分类Dev

DBD :: MySql初始化失败:使用生物信息学工具OrthoMCL时无法通过包“ DBD :: MySql”找到对象方法“ driver”

来自分类Dev

对Firebase崩溃报告进行了模糊处理,没有行号

来自分类Dev

我如何找出程序的安装程序进行了哪些修改?

来自分类Dev

在Perl中将Convert-> numrows与DBD :: mysql一起使用

来自分类Dev

Apache dbd内部错误:AH00629:无法连接到mysql

来自分类Dev

DBD :: Oracle-一个PL / SQL块不起作用

Related 相关文章

  1. 1

    使用DBI / DBD :: PG的Postgresql框类型的占位符

  2. 2

    无法编译DBD-Oracle-1.74 | 找不到DBI.pm

  3. 3

    Ubuntu 上的 Apache 2.4:“无法加载驱动程序文件 apr_dbd_oracle.so”

  4. 4

    安装DBD :: Oracle时出错

  5. 5

    Apache2 Auth dbd-数据库中的md5哈希密码,但是apache将其与原始密码进行比较

  6. 6

    在Mac上安装perl DBD:Pg

  7. 7

    DBD :: ODBC与Win32 :: odbc

  8. 8

    Linux:如何安装DBD :: Pg模块?

  9. 9

    DBD :: SQLite插入多行的最快方法

  10. 10

    安装perl-DBD-mysql时出错

  11. 11

    Linux:如何安装DBD :: Pg模块?

  12. 12

    Perl:DBD :: ODBC :: st执行失败

  13. 13

    仅保存如果进行了更改

  14. 14

    尽管进行了错误处理,Windows 8.1 XAML应用程序仍然崩溃

  15. 15

    Perl和DBD :: Oracle-可提取多少行?RowsInCache?

  16. 16

    How to install the perl module DBD::Sybase on Unix (Mac OSX)?

  17. 17

    DBD :: mysql :: st执行失败:MySQL服务器消失了

  18. 18

    Perl和DBD :: Oracle-可提取多少行?RowsInCache?

  19. 19

    在配置投影时,Vertica DBD是否考虑内部查询?

  20. 20

    DBD :: Oracle :: st执行失败:系统生成的消息

  21. 21

    Perl install_driver(Oracle)失败:-无法为模块DBD :: Oracle Win64加载'../DBD/Oracle/Oracle.dll'

  22. 22

    DES程序进行了很多回合。

  23. 23

    尝试创建python程序,但使用def进行了简化

  24. 24

    DBD :: MySql初始化失败:使用生物信息学工具OrthoMCL时无法通过包“ DBD :: MySql”找到对象方法“ driver”

  25. 25

    对Firebase崩溃报告进行了模糊处理,没有行号

  26. 26

    我如何找出程序的安装程序进行了哪些修改?

  27. 27

    在Perl中将Convert-> numrows与DBD :: mysql一起使用

  28. 28

    Apache dbd内部错误:AH00629:无法连接到mysql

  29. 29

    DBD :: Oracle-一个PL / SQL块不起作用

热门标签

归档