Задавайте вопросы, мы ответим
Вы не зашли.
Ситуация т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 ?
Спасибо.
Неактивен
Пока клиент удерживает явную блокировку, он не может использовать другие таблицы, поэтому блокировать нужно сразу все что понадобится (одним выражением), так как повторное использование оператора LOCK TABLES отменяет сделанные ранее блокировки.
http://sqlinfo.ru/articles/info/10.html
Неактивен
Вы имеете виду в LOCK TABLES video_stats v WRITE , добавить ещё video_stats_tmp1 s READ ?
То есть так ? LOCK TABLES video_stats v WRITE ,video_stats_tmp1 s READ ?
Делал не помогает.
Или вы имеете виду что закрывать таблицу бессмысленно так как другой LOCK TABLES с другого процесса заново откроет её, и сного произойдёт ошибка ?
Неактивен
А в чем проявляется «не помогает»?
Неактивен
paulus написал:
А в чем проявляется «не помогает»?
Срабатывает LOCK TABLES и первый же UPDATE висит пока не пройдёт timeout или не запустится другой LOCK TABLES.
Ошибка Deadlock found when trying to get lock; try restarting transaction
возникает и в других таблицах, когда выполняется одновременная запись в одну таблицу, правда во всех случаях идёт речь о updat-aх обновляющие все поля таблицы.
Вроде такая баналльная вещь обновить все поля таблицы ...
Ведь как то должно это решаться в Mysql-е ?
Неактивен
В один ли поток Ваш dbapp обрабатывает соединения? Не начинает
ли он транзакции? Действительно ли у Вас блокируется таблица?
Делаете ли Вы эти изменения всех данных в один поток или может
прийти больше потоков? Если Вы хотите блокировать таблицу целиком
и обновлять ее целиком, нужна ли Вам вообще таблица InnoDB?
Неактивен
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)
Неактивен
1. Если UPDATE висит в состоянии locked — это значит, что он пытается
получить блокировку. Или другой поток пришел с обычным UPDATE и
мы ждем, когда он отпустит свои строчные блокировки, или он пришел
с LOCK TABLES, но в любом случае текущий поток не заблокировал
таблицу с помощью LOCK TABLES.
2. Если Вы в несколько потоков собираетесь в одну транзакцию обновлять
несколько миллионов строк, пересмотрите архитектуру приложения. Навер-
няка оно может быть улучшено. В крайнем случае — ограничиться одним
потоком, который будет наполнять соседнюю табличку, а потом переимено-
вывать их. Ну и MyISAM всё-таки при таком использовании.
3. Другой поток не может открыть то, что закрыл этот. Смотрите, как работает
Ваш класс. Скорее всего, он кидает Ваши запросы по независимым соедине-
ниям.
Неактивен
Вроде бы делаю правильный запрос.
<?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)
Неактивен
А в это время другие процессы обращаются к этой табличке?
Ну и еще предположение: innodb_table_locks включен ведь?
Неактивен