Задавайте вопросы, мы ответим
Вы не зашли.
Приветствую.
Ситуация:
Windows XP SP3+
MySQL: 4.1.22, 5.0.67, 5.1.28
ActivePerl: 5.8.7.815, 5.10.0.1004
DBD-mysql: 3.0002, 4.005
Скрипт многократно в цикле читает данные из таблицы (~120000 записей древовидной структуры), преобразовывает их и пишет в файл.
На компьютере 700МГц+512МБ работает штатно.
На компьютерах 2x3400МГц+1024МБ и 2x3400МГц+2048МБ:
. завершается с ошибкой выполнения селекта через несколько сотен запросов;
. если после завершения селекта по $sth -> finish() поставить:
. . sleep(1) - то же самое.
. . sleep(2) - работает, но, что очевидно, недопустимо медленно.
Сталкивался кто-нибудь с подобным?
Неактивен
А какая ошибка выполнения селекта?
Полагаю, дело не в железе, а то, что в одном случае это тестовая база, а во втором - боевая.
В боевой есть еще какие-то запросы, наверняка, которые могут лочить/что-то еще.
Без текста ошибки, боюсь, не справимся
UPD:
Подумал, что никогда не пользуюсь finish, залез в CPAN, с интересом увидел, что не зря:
http://search.cpan.org/~timb/DBI-1.607/DBI.pm#finish
У Вас какие-то принципиальные соображения на этот счет?
Неактивен
Не знаю.
В условии if ( !$sth->execute() )
$dbh->err() и if $dbh->errstr() пустые
Неактивен
paulus написал:
Подумал, что никогда не пользуюсь finish, залез в CPAN, с интересом увидел, что не зря:
http://search.cpan.org/~timb/DBI-1.607/DBI.pm#finish
У Вас какие-то принципиальные соображения на этот счет?
Привычка закрывать сессию или объект.
Удаление finish не повлияло ни на что.
Неактивен
Насколько я понимаю, нужно именно $dbh->errstr...
Насколько большие получаются выборки данных? Все 120к записей? Используете ли
mysql_use_result, если да?
Можете ли параллельно открыть отдельный коннект сразу после завершения вот этой
"подвисшей" операции и спросить "SHOW PROCESSLIST" - что будет написано для вот
этого "подвисшего" соединения?
Неактивен
Реакции никакой в: $err.= " err:[".$dbh->errstr()."]" if $dbh->errstr();
Сейчас вылетает на 2826 записи. Место вылета стабильное. Иногда меняется не понятно почему.
Show processlist выдаёт одну строку. Если успеть во время выполнения, то две.
Отредактированно Uniol (17.10.2008 20:37:13)
Неактивен
Как использовать mysql_use_result в DBI?
В варианте $sth = $dbh->prepare($cmd { "mysql_use_result" => 1});
получаю
Global symbol "%cmd" requires explicit package at ...
Неактивен
$dbh->{'mysql_use_result'}=1;
Позволяет не вытаскивать все данные в память перед тем, как отдать их в perl,
в принципе, более удачный способ для вытаскивания больших блоков данных
(mysql_store_result, по-умолчанию который, вытаскивает все данные одним куском).
А что за строки show processlist? Состояние Sleep или что-то еще?
Неактивен
С $dbh->{'mysql_use_result'}=1; вылетет на 2й строке
Без неё на 3102-й
О! Один косяк исправил. $sth->finish() был до $dbh->errstr()
Ошибка
Commands out of sync; you can't run this command now
Неактивен
Коллега, благодарю Вас за консультацию. Сейчас должен покинуть рабочее помещение.
Неактивен
У консоли Query, у скрипта Sleep
Неактивен
С $dbh->{'mysql_use_result'}=1 вылетет на 2й строке с "Commands out of sync; you can't run this command now"
Без $dbh->{'mysql_use_result'}=1 вылетет на 293й строке с "Table '' is read only"
Это косяк BDI? Как вывернуться?
Неактивен
Не могу найти, как с ->{'mysql_use_result'}=1 выполнить подряд много ->prepare c ->execute.
Во всех примерах только один раз.
Не коннектиться же заново...
Неактивен
А сам сценарий секретный? Можете показать его содержимое?
Ошибка "Commands out of sync; you can't run this command now" обычно возникает тогда,
когда Вы недовытащили данные предыдущего запроса, а хотите в этом же соединении
подготовить следующий запрос.
Неактивен
Скрипт вовсе не секретный. См: http://forum.ixbt.com/topic.cgi?id=24:41199
По-хорошему, его надо почистить от мусора... Но проблема не в нём.
Как я понял, ->{'mysql_use_result'}=1 можно использовать, если в скрипте один проход по таблицам, а в моём случае их много.
Насколько я понимаю, это глюк интерфейса в чистом виде.
Неактивен
А что за модуль dbase? Какая-то надстройка над DBI?
Я не уверен, что закрывать надо sth->finish. Скорее всего, в обертке есть
своя функция закрытия, которую надо использовать.
Мой совет - переписать, используя DBI. Будет и проще, и работать будет.
Неактивен
Закрывать объёкты лучше в явном виде и не полагаться на сборщики мусора. sth->finish - корректное закрытие запроса.
dbase - "надстройка" над DBI.
пример функции go из пакета dbase:
sub go
{
my ($this, $cmd, $label) = @_;
my $dbh = $this->{_}{dbh};
my $sth;
return if !$cmd;
$label = "" if !$label;
if ( !$this->{_}{error} )
{
if ( !$dbh ) { print "dbase.pm:go:dbh:'$cmd'<br>"; }
else
{
if ( $sth = $dbh->prepare($cmd) )
{
if ( !$sth->execute() )
{
$this->error("'$label'::[".$dbh->err()."]".$dbh->errstr().": [$cmd]");
$sth->finish(); undef $sth;
}
}
else
{
$label = "" if !defined($label);
$this->error("Cannot prepare in '$label'.[$cmd]");
}
}
}
return $sth;
}
Каждый раз писать это в явном виде, полагаю, не правильно.
ЗЫ
На MySQL 6 alpha+ActivePerl-5.10.0.1004+DBI 4.005 работает со sleep(1).
Точно косяк. Было бы время, покопался бы с исходниками DBI.
Отредактированно Uniol (22.10.2008 13:11:35)
Неактивен
Кстати. MySQL 6.0 при {'mysql_use_result'}=0 выдаёт при вылете ошибку: File: 'C:\WINDOWS\TEMP\#sql_c32_0.MAD' is read only
Количество селектов до вылета не постоянно.
Антивирусы и пр. отключал. На результат не влияет.
Неактивен
Закрывать объёкты лучше в явном виде и не полагаться на сборщики мусора.
sth->finish - корректное закрытие запроса.
Будьте последовательны. Или пользуйтесь "высокими" технологиями типа крутых (?)
библиотек и используйте их способы доступа к БД, или используйте то, чем пользуется
весь остальной мир - DBI - и тогда закрывайте запросы правильно.
Неактивен
DBI устраивало, пока работало.
Как правильно закрывать в DBI, если не по $sth->finish()?
Отредактированно Uniol (22.10.2008 19:45:47)
Неактивен
То, что является надстройкой над DBI, все-таки, его использует. Поэтому не надо
надеяться, что надстройка будет работать при том, что не работает базовое.
Другое дело, что базовое оттачивалось годами, и используется тысячами программистов
по всему миру. Вероятность того, что оно не работает - очень мала. Хотя, конечно,
опять-таки зависит от реализации.
Я бы на Вашем месте переписал всё на чистом DBI, причем с нормальными
плейсхолдерами, то, что называется "by the book".
Альтернативный вариант - попробовать другую сборку perl (можно и самому собрать,
кстати). Что ActivePerl меняет в исходниках - никому не известно.
Неактивен
Я так понимаю, тема себя исчерпала.
Предлагаются удары в бубен и камлание. А так же вера в непогрешимость тыщ программистов, годами оттачивавших DBI, который не смотря на все усилия не имеет ни средств трассировки, ни нормальных сообщений об ошибках.
Ладно. Благодарю Вас, коллега, за консультации.
Кстати, камлание выявило забавное свойство.
При последовательных запусках скрипта количество обрабатываемых записей увеличивается. То есть, запрашивается некий страничный ресурс, при нехватке которого происходит дополнительное его выделение, но система возвращает ошибку. Именно в момент выделения в папке для временных файов появляются два файла по 8К с расширениями MAD и MAI.
Отредактированно Uniol (27.10.2008 12:15:37)
Неактивен
Проблема решилась после замены типа данных для одного из полей таблицы с text на varchar(512).
Данный скрипт писался давно для mysql 3.х у которого тип varchar был не длиннее 255 и данные в нем не помещались.
В общем, как и ожидалось, причина - кривой интерфейс.
Отредактированно Uniol (06.11.2008 13:13:38)
Неактивен