Perl DBI: ODBC сбой / использование странного файла - PullRequest
2 голосов
/ 13 марта 2012

Я пытаюсь решить проблему, из-за которой происходит сбой скрипта с информацией об ошибке «практически нет» на одном сервере (db1), но не на другом сервере (db2), несмотря на то, что обе среды идентичны в каждом путь (кроме одного), который я могу найти.

Вот сценарий, test.pl:

use strict;
use warnings;

use DBI;
use Data::Dumper;

$ENV{LD_LIBRARY_PATH} = "/var/local/odbc";
$ENV{ODBCHOME}        = "/var/local/odbc";
$ENV{ODBCINI}         = "/etc/odbc.ini";

my $dbh = DBI->connect( "dbi:ODBC:db", "foo", "bar" ) or die "$DBI::err\n$DBI::errstr\n$DBI::state\n";
$dbh->{RaiseError} = "0";
$dbh->{AutoCommit} = "1";
$dbh->{LongReadLen} = 1024;

#$dbh->{TraceLevel} = 10;

my $sth = $dbh->prepare( "SELECT * FROM table WHERE x='y'" ) or die "$DBI::err\n$DBI::errstr\n$DBI::state\n";
$sth->execute or die "$DBI::err\n$DBI::errstr\n$DBI::state\n";

my $data = $sth->fetchall_hashref( 'x' );
print Data::Dumper->Dump( [$data] );

А вот вывод (примечание: смерть наступила на $sth->execute):

$ ./test
DBD::ODBC::st execute failed: [DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1) at ./test line 24.
-1
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)
HY000

TraceLevel 10 не проливает свет на меня:

$ ./test
    DBI::db=HASH(0x1f2cc8e0) trace level set to 0x0/10 (DBI @ 0x0/0) in DBI 1.52-ithread (pid 27494)
    -> prepare for DBD::ODBC::db (DBI::db=HASH(0x1f2cc510)~0x1f2cc8e0 'SELECT * FROM table WHERE x='y'') thr#1effa010
    dbih_setup_handle(DBI::st=HASH(0x1f2cca60)=>DBI::st=HASH(0x1f2ccb60), DBD::ODBC::st, 1f2cca70, Null!)
    dbih_make_com(DBI::db=HASH(0x1f2cc8e0), 1f2d1e30, DBD::ODBC::st, 376, 0) thr#1effa010
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), Err, DBI::db=HASH(0x1f2cc8e0)) SCALAR(0x1f183620) (already defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), State, DBI::db=HASH(0x1f2cc8e0)) SCALAR(0x1f1836a0) (already defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), Errstr, DBI::db=HASH(0x1f2cc8e0)) SCALAR(0x1f183660) (already defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), TraceLevel, DBI::db=HASH(0x1f2cc8e0)) 10 (already defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), FetchHashKeyName, DBI::db=HASH(0x1f2cc8e0)) 'NAME' (already defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), HandleSetErr, DBI::db=HASH(0x1f2cc8e0)) undef (not defined)
    dbih_setup_attrib(DBI::st=HASH(0x1f2ccb60), HandleError, DBI::db=HASH(0x1f2cc8e0)) undef (not defined)
    initializing sth query timeout to 0
    ignore named placeholders = 0
    SQLPrepare returned 0

    dbd_st_prepare'd sql f523212832, ExecDirect=0
        SELECT * FROM table WHERE x='y'
    <- prepare= DBI::st=HASH(0x1f2cca60) at ./test line 23
    -> execute for DBD::ODBC::st (DBI::st=HASH(0x1f2cca60)~0x1f2ccb60) thr#1effa010
    dbd_st_execute (outparams = 0)...
    dbd_st_execute (for hstmt 523212832 before)...
    dbd_st_execute (for hstmt 523212832 after, rc = -1)...
dbd_error: err_rc=-1 rc=0 s/d/e: 523212832/523051280/523050880
dbd_error: SQL-HY000 (native 0): [DataDirect][ODBC SQL Server Driver] (SQL-HY000)
dbd_error: SQL-HY000 (native 0): [DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
dbd_error: err_rc=-1 rc=0 s/d/e: 0/523051280/523050880
dbd_error: err_rc=-1 rc=0 s/d/e: 0/0/523050880
st_execute/SQLExecute error -1 recorded: [DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)
    !! ERROR: -1 '[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)' (err#0)
    <- execute= undef at ./test line 24
DBD::ODBC::st execute failed: [DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1) at ./test line 24.
-1
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)
HY000
    -> DESTROY for DBD::ODBC::st (DBI::st=HASH(0x1f2ccb60)~INNER) thr#1effa010
   SQLFreeStmt called, returned 0.
       ERROR: -1 '[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)' (err#0)
    <- DESTROY= undef
    -> DESTROY for DBD::ODBC::db (DBI::db=HASH(0x1f2cc8e0)~INNER) thr#1effa010
  DBD::ODBC Disconnected!
       ERROR: -1 '[DataDirect][ODBC SQL Server Driver] (SQL-HY000)
[DataDirect][ODBC SQL Server Driver] (SQL-HY000)(DBD: st_execute/SQLExecute err=-1)' (err#0)
    <- DESTROY= undef

I strace d запускается на обоих серверах, и ЕДИНСТВЕННАЯ разница возникает в конце выполнения, когда сценарий на db1 пытается открыть и прочитать файл /var/local/odbc/DDODBC.DAT и переходит к аварийному завершению. Запуск на db2 ничего не делает и продолжает успешно работать. После большого количества сканирования и сравнения файловой системы я подтвердил, что файлы конфигурации odbc.ini одинаковы для обоих серверов и что вся структура и содержимое / var / local / odbc также одинаковы, за исключением DDODBC .DAT существует в db1, но не db2. Переменные среды также одинаковы.

Перемещение DDODBC.DAT в другое место приводит к успешному выполнению сценария. Файл воссоздается, используется, а затем скрипт выполняет свою работу (как видно из strace). Если я заменю оригинальный DDODBC.DAT, сценарий снова падает. Очевидным выводом здесь является то, что файл был ошибочным, с плохими данными, повреждением или тому подобным strace на новом, успешном, пробеги на db1 отличаются только от тех на db2 на четыре линии:

open("/var/local/odbc/DDODBC.DAT", O_RDONLY) = 4
lseek(4, 0, SEEK_SET)                   = 0
read(4, ..., 1212) = 1212
close(4)                                = 0

Для чего используется файл DDODBC.DAT и для чего он создается? Googles мне не помогли.

Для записи:

$ perl --version
This is perl, v5.8.8 built for x86_64-linux-thread-multi
$ uname -srmo
Linux 2.6.18-141.el5 x86_64 GNU/Linux
$ odbcinst --version
unixODBC 2.2.11
$ perl -MDBD::ODBC -e 'print $DBD::ODBC::VERSION, "\n";'
1.13

Ответы [ 2 ]

1 голос
/ 13 марта 2012

Полагаю, вам придется поговорить с вашим поставщиком драйверов, поскольку я знаю, что DBD :: ODBC не использует файл DDODBC.DAT и, исходя из названия, предлагает DataDirect.Трассировка показывает вызов ошибок SQLExecute и возвращает общую ошибку (HY000) без текста ошибки.

0 голосов
/ 20 марта 2012

DataDirect подтвердил, что файл DDODBC.DAT (обычно) создается при возникновении конфликта лицензирования на хосте. В нашем случае наша лицензия предназначена для серверов с максимум 16 процессорами, однако мы установили драйвер на хост с 24 процессорами. Драйвер понял это, запомнил это (с помощью DDODBC.DAT) и, в конце концов, переключится в режим оценки.

...