Это сложно объяснить (и очень странно), так что потерпите меня. Я объясню проблему и исправление для нее, но я хотел бы посмотреть, может ли кто-нибудь объяснить, почему это работает так, как работает :)
У меня есть веб-приложение, которое использует mod_perl. Он использует базу данных MySQL, и я регулярно записываю данные в базу данных. Он модульный, поэтому он также имеет свой собственный тип модуля «база данных», где я обрабатываю соединение, обновления и т. д. Для подключения к базе данных используется подпрограмма database::db_connect(), а AutoCommit
установлено в 0.
Я сделал еще одно приложение Perl (автономный демон), которое периодически извлекает данные из базы данных и выполняет различные задачи в зависимости от того, какие данные возвращаются. Я включаю в него модуль database.pm, поэтому мне не нужно все переписывать/дублировать.
Проблема, с которой я сталкиваюсь:
Приложение подключается к базе данных при запуске, а затем бесконечно зацикливается, извлекая данные из базы данных каждые X секунд. Однако, если данные в базе данных обновляются, моему приложению по-прежнему возвращаются «старые» данные, которые я получил при первоначальном подключении/запросе к базе данных.
Например, у меня есть 3 строки, а столбец «Имя» имеет значения «a», «b» и «c» для каждой записи. Если я обновлю одну из строк (например, с помощью клиента mysql из командной строки) и изменю имя с «c» на «x», мой автономный демон не получит эти данные — он все равно получит a/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).
auto_commit
в вашем клиенте mysql командной строки (где вы выполняли операциюUPDATE
)? - person Ether   schedule 17.10.2010