SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 22.02.2010 21:44:50

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Deadlock found when trying to get lock

Ситуация тaкая, раз в минуту  на разных серверах запускается cron.
Который запускает php пишущий в одну и туже таблицу video_stats

Server 1

Код:

   UPDATE video_stats v,video_stats_tmp1 s
        SET v.views=v.views+s.views
        WHERE v.video_id = s.video_id;

Server 2

Код:

   UPDATE video_stats v,video_stats_tmp2 s
        SET v.views=v.views+s.views
        WHERE v.video_id = s.video_id;

Mysql падает на : Deadlock found when trying to get lock; try restarting transaction

Закрываю таблицу.

Код:

$dbapp->query('LOCK TABLES video_stats v WRITE');
$dbapp->query("
        UPDATE video_stats v,video_stats_tmp1 s
        SET v.views=v.views+s.views
        WHERE v.video_id = s.video_id");
$dbapp->query('COMMIT');
$dbapp->query('UNLOCK TABLES');

После LOCK-a , UPDATE вообще не срабатывает и висит закрытая таблица.

Подскажите что вообще происходит ?
Почему 2 запроса одновременно не могут писать в одну таблицу ?
Что не правильного в использовании LOCK TABLES ?
Спасибо.

Неактивен

 

#2 23.02.2010 00:15:40

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Deadlock found when trying to get lock

Пока клиент удерживает явную блокировку, он не может использовать другие таблицы, поэтому блокировать нужно сразу все что понадобится (одним выражением), так как повторное использование оператора LOCK TABLES отменяет сделанные ранее блокировки.

http://sqlinfo.ru/articles/info/10.html

Неактивен

 

#3 23.02.2010 09:16:11

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Deadlock found when trying to get lock

Вы имеете виду в LOCK TABLES video_stats v WRITE , добавить ещё video_stats_tmp1 s READ ?
То есть так ? LOCK TABLES video_stats v WRITE ,video_stats_tmp1 s READ ?
Делал не помогает.

Или вы имеете виду что закрывать таблицу бессмысленно так как другой LOCK TABLES с другого процесса заново откроет её, и сного произойдёт ошибка ?

Неактивен

 

#4 23.02.2010 16:35:00

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Deadlock found when trying to get lock

А в чем проявляется «не помогает»?

Неактивен

 

#5 23.02.2010 16:50:16

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Deadlock found when trying to get lock

paulus написал:

А в чем проявляется «не помогает»?

Срабатывает LOCK TABLES и первый же UPDATE висит пока не пройдёт timeout или не запустится другой LOCK TABLES.

Ошибка Deadlock found when trying to get lock; try restarting transaction
возникает и в других таблицах, когда выполняется одновременная запись в одну таблицу, правда во всех случаях идёт речь о updat-aх обновляющие все поля таблицы.

Вроде такая баналльная вещь обновить все поля таблицы ...
Ведь как то должно это решаться в Mysql-е ?

Неактивен

 

#6 23.02.2010 16:55:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Deadlock found when trying to get lock

В один ли поток Ваш dbapp обрабатывает соединения? Не начинает
ли он транзакции? Действительно ли у Вас блокируется таблица?
Делаете ли Вы эти изменения всех данных в один поток или может
прийти больше потоков? Если Вы хотите блокировать таблицу целиком
и обновлять ее целиком, нужна ли Вам вообще таблица InnoDB?

Неактивен

 

#7 23.02.2010 17:10:14

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Deadlock found when trying to get lock

paulus написал:

В один ли поток Ваш dbapp обрабатывает соединения?

$dbapp->query('LOCK TABLES video_stats v WRITE');
$dbapp->query("
        UPDATE video_stats v,video_stats_tmp1 s
        SET v.views=v.views+s.views
        WHERE v.video_id = s.video_id");
$dbapp->query('COMMIT');
$dbapp->query('UNLOCK TABLES');

Ну по идее в один. А как это проверить ?
Вы имеете виду что может в самом db классе запорка ?

paulus написал:

Не начинает ли он транзакции?

Не понял что вы имеете виду.

paulus написал:

Действительно ли у Вас блокируется таблица?

UPDATE - висит под статусом locked

paulus написал:

Делаете ли Вы эти изменения всех данных в один поток или может
прийти больше потоков?

Может быть ситуация когда идёт много разных потоков, в этом случае хотелось бы чтоб они становились в очередь и выполнялись один за другим.
В таком случае LOCK TABLES может ли помочь вообще ? Не получится ли ситуация что один поток закрыл а второй открыл ?


paulus написал:

нужна ли Вам вообще таблица InnoDB?

Предполагается что таблица будет больших размеров несколько миллионов rows, поэтому дал предпочтениe INNODB.

Отредактированно evgeny (23.02.2010 17:11:36)

Неактивен

 

#8 23.02.2010 17:17:29

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Deadlock found when trying to get lock

1. Если UPDATE висит в состоянии locked — это значит, что он пытается
получить блокировку. Или другой поток пришел с обычным UPDATE и
мы ждем, когда он отпустит свои строчные блокировки, или он пришел
с LOCK TABLES, но в любом случае текущий поток не заблокировал
таблицу с помощью LOCK TABLES.

2. Если Вы в несколько потоков собираетесь в одну транзакцию обновлять
несколько миллионов строк, пересмотрите архитектуру приложения. Навер-
няка оно может быть улучшено. В крайнем случае — ограничиться одним
потоком, который будет наполнять соседнюю табличку, а потом переимено-
вывать их. Ну и MyISAM всё-таки при таком использовании.

3. Другой поток не может открыть то, что закрыл этот. Смотрите, как работает
Ваш класс. Скорее всего, он кидает Ваши запросы по независимым соедине-
ниям.

Неактивен

 

#9 25.02.2010 14:29:24

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Deadlock found when trying to get lock

Вроде бы делаю правильный запрос.

Код:

<?php
$link = mysqli_connect(LBHOST,LBUSER,LBPASS, LBNAME);
mysqli_query($link, "LOCK TABLES stats WRITE");
mysqli_query($link, "update stats set status=444 where id=8312");
mysqli_query($link, "UNLOCK TABLES");
mysqli_close($link);
?>

Запускаю php , иногда срабатывает быстро, а иногда зависает и висит пол минуты.
В случаях когда висит, в show processlist  пишет:
Locked update stats set status=444 where id=8312

Объясните пожалуйста что происходит ?

Отредактированно evgeny (25.02.2010 15:10:58)

Неактивен

 

#10 25.02.2010 21:07:08

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Deadlock found when trying to get lock

А в это время другие процессы обращаются к этой табличке?

Ну и еще предположение: innodb_table_locks включен ведь?

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson