обработка данных с помощью Perl - выбор использования обновлений с помощью MySQL - PullRequest
1 голос
/ 16 октября 2011

У меня есть таблица, в которой хранятся данные, которые необходимо обработать.У меня есть идентификатор, статус, данные в таблице.Я сейчас прохожу и выбираю идентификатор, данные, где статус = #.Затем я делаю обновление сразу после выбора, меняя статус #, чтобы он больше не выбирался.

моя программа многопоточная, и иногда я получаю потоки, которые получают тот же идентификатор, что и они обазапросы к таблице в относительно близкое время друг к другу, вызывая захват одного и того же идентификатора.Я посмотрел в выбор для обновления, однако, я либо сделал запрос неправильно, или я не понимаю, для чего он используется.

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

  my $select = $db->prepare("SELECT id, data FROM `TestTable` WHERE _status=4 LIMIT ? FOR UPDATE") or die $DBI::errstr;
if ($select->execute($limit))
     {
       while ($data = $select->fetchrow_hashref())
            { 

                my $update_status = $db->prepare( "UPDATE `TestTable` SET _status = ?, data = ? WHERE _id=?");
                    $update_status->execute(10, "", $data->{_id});
        push(@array_hash, $data);

             }
     }

когда я запускаю это, если я выполняю несколько потоков, я получаю много повторяющихся вставок, когда пытаюсь выполнить вставку после обработки данных моей транзакции.

Я не очень хорошо знаком с MySQL и проведенным мною исследованием. Я не нашел ничего, что действительно прояснило бы это для меня.

спасибо

Ответы [ 2 ]

1 голос
/ 17 октября 2011

В качестве проверки работоспособности вы используете InnoDB? MyISAM имеет нулевую поддержку транзакций, кроме фальсификации с полной блокировкой таблицы.

Я не вижу, где вы начинаете транзакцию. Параметр MySQL autocommit включен по умолчанию, поэтому запуск транзакции и последующее принятие будут необходимы, если вы не выключите autocommit.

0 голосов
/ 17 октября 2011

Похоже, вы просто полагаетесь на механизмы блокировки базы данных.Я погуглил perl dbi locking и нашел this :

$dbh->do("LOCK TABLES foo WRITE, bar READ");
$sth->prepare("SELECT x,y,z FROM bar");
$sth2->prepare("INSERT INTO foo SET a = ?");
while (@ary = $sth->fetchrow_array()) {
    $sth2->$execute($ary[0]);
    }
$sth2->finish();
$sth->finish();
$dbh->do("UNLOCK TABLES");

Не совсем говорю GIYF, так как я также довольно новичок в MySQL и DBI, но, возможно, вы можете найти другие ответы таким образом.

Другой вариант может быть следующим, и это работает, только если вы контролируете весь код, обращающийся к данным.Вы можете создать lock столбец в таблице.Когда ваш код обращается к таблице (псевдокод):

if row.lock != 1 
  row.lock = 1
  read row
  update row
  row.lock = 0
  next
else 
  sleep 1
  redo

снова, это значит, что все пользователи / сценарии, которые получают доступ к этим данным, согласятся следовать этой политике.Если вы не можете гарантировать, что это не сработает.

В любом случае, это все знания, которые у меня есть по этой теме.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...