Это сложно объяснить (и очень странно), так что терпите меня. Я объясню проблему и ее решение, но я хотел бы посмотреть, сможет ли кто-нибудь объяснить, почему она работает так, как она работает:)
У меня есть веб-приложение, которое использует mod_perl. Он использует базу данных MySQL, и я регулярно записываю данные в базу данных. Он является модульным, поэтому он также имеет свой собственный тип модуля «база данных», где я обрабатываю соединение, обновления и т. Д. Подпрограмма database :: db_connect () используется для подключения к базе данных, а AutoCommit
имеет значение 0.
Я создал другое приложение Perl (автономный демон), которое периодически извлекает данные из базы данных и выполняет различные задачи в зависимости от того, какие данные возвращаются. Я включил в него модуль database.pm, поэтому мне не нужно все переписывать / дублировать.
Проблема, с которой я столкнулся:
Приложение подключается к базе данных при запуске, а затем зацикливается, извлекая данные из базы данных каждые X секунд. Однако, если данные в базе данных обновляются, моему приложению все еще возвращаются «старые» данные, которые я получил при первоначальном подключении / запросе к базе данных.
Например - у меня есть 3 строки, а столбец «Имя» имеет значения «a», «b» и «c» - для каждой записи. Если я обновлю одну из строк (например, с помощью клиента mysql из командной строки) и изменит имя с 'c' на 'x', мой автономный демон не получит эти данные - он все равно получит / b / c, возвращенный из MySQL. Я перехватил трафик базы данных с помощью tcpdump и определенно мог видеть, что MySQL действительно возвращает эти данные. Я также пытался использовать SQL_NO_CACHE с SELECT (поскольку я не был уверен, что происходит), но это тоже не помогло.
Затем я изменил строку подключения к БД в своем автономном демоне и установил AutoCommit
в 1. Внезапно приложение начало получать правильные данные.
Я озадачен, потому что я думал, что AutoCommit влияет только на операторы типа INSERT / UPDATE и не влияет на оператор SELECT. Но, похоже, это так, и я не понимаю, почему.
Кто-нибудь знает, почему оператор SELECT не будет возвращать «обновленные» строки из базы данных, когда AutoCommit
установлен в 0, и почему он будет возвращать обновленные строки, когда AutoCommit
установлен в 1?
Вот упрощенный (удаленный контроль ошибок и т. Д.) Код, который я использую в автономном демоне и который не возвращает обновленные строки.
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
$|=1;
my $dsn = "dbi:mysql:database=mp;mysql_read_default_file=/etc/mysql/database.cnf";
my $dbh = DBI->connect($dsn, undef, undef, {RaiseError => 0, AutoCommit => 0});
$dbh->{mysql_enable_utf8} = 1;
while(1)
{
my $sql = "SELECT * FROM queue";
my $stb = $dbh->prepare($sql);
my $ret_hashref = $dbh->selectall_hashref($sql, "ID");
print Dumper($ret_hashref);
sleep(30);
}
exit;
Изменение AutoCommit
на 1 исправляет это. Почему?
Спасибо:)
P.S: Не уверен, что кому-то все равно, но версия DBI - 1.613, DBD :: mysql - 4.017, perl - 5.10.1 (в Ubuntu 10.04).