Задавайте вопросы, мы ответим
Вы не зашли.
Ситуация - подрезка данных, идёт удаление из таблицы. Условие удаления - по полю, на который есть индекс. Процесс удаления длится уже более 9 часов. Количество записей в районе 10 миллионов, отрезается примерно 20%. Проблема в том, что таблица заблокирована, хотя, как я понимаю, заблокирована быть не должна. Что можно посмотреть, чтобы понять причину блокировки?
И вторая часть проблемы... Я пытаюсь отменить запрос с удалением командой kill query, мне пишет что всё ок, отработало. Однако, на самом деле запрос продолжает висеть и блокировать таблицу. Пробую kill connection - ноль эмоций. Таким образом, вопрос номер 2 - как бы мне всё-таки его удалить?
Отредактированно Lem0nti (16.12.2008 15:12:55)
Неактивен
Все зависит от условия. Если условие простое (=, IN), то блокируются только удаляемые записи, а если сложное (в том числе >,<) - вся таблица.. Делайте сначала SELECT, а потом удаляйте по ID кусками.
Иногда процесс не убивается, это бага, если можете повторить пишите на bugs.mysql.com и ссылку сюда.
Неактивен
Немного переделал запрос, теперь удаляется по первичному ключу. Условие - "<=". Подрезка прошла за 2 часа, но блокировка таблицы всё-равно была.
Подскажите, пожалуйста, где я могу в документации на том же mysql.com посмотреть подробности по этим условиям? Просто по поводу тех же блокировок, ситуация такова - есть несколько боевых объектов. На них эта подрезка происходит до 55 минут. Нигде, кроме вот одного конкретного места не присутствует проблем, связанных с блокировками. Блокировка начиналась с момента начала удаления - я проверил сейчас с утра все экземпляры системы.
Возникло ещё предположение, что блокируется не конкретно моя таблица, а связанные справочные таблицы. Впоследствии, организую поподробнее протоколирование при блокировках, но как бы то ни было - не можете ли вы чего-нибудь написать и по этому поводу?
Неактивен
<= блокирует всю таблицу. Стоит сначала выполнять SELECT, а потом уже DELETE ... WHERE ID IN (...)
Неактивен
Добавлю немного по поводу убиения: поток не обязан убиваться моментально (особенно в случае
с InnoDB): изменения в таблице приводят к дублированию информации (для возможности откатывания
транзакции). Также SELECT других потоков, находящихся в уровне изоляции старше, чем
READ UNCOMMITTED приводят к дублированию. Убитый поток освобождает эти занятые ресурсы, а
только потом умирает. Разумеется, багой это не является.
UPD:
Ну и, разумеется, если в InnoDB Вы выбираете не по первичному ключу записи для удаления, то gap
будет блокироваться как по вторичному, так и по первичному ключу (из-за того, что он кластерный).
Неактивен
Ситуация с убиением потока - были завершены все приложения, работающие с базой, что подтверждалось списком задач при show processlist. По времени после kill query я ждал завершения около часа, потом просто срубил майку. Немного не понял про gap. Да и потом я переделал на первичный ключ - блокировка осталась. И как мне понимать, что такое происходит только в одном месте? Версия софта везде одинакова, версия майки везде одинакова. Может быть на это влияют ещё какие-нибудь настройки?
Неактивен
А после kill - поток остается висеть в show processlist?
Неактивен
Именно. И после kill query и после kill connection. И даже в столбце comand ничего не поменялось, что могло бы мне сообщить что убивание процесса началось.
Неактивен
Должно было проставиться state=killed...
В документации сказано, что MySQL проверяет состояние флага killed на каждую удаленную строку.
Если сервер очень-очень загружен по дискам, то теоретически он может это делать долго... но не несколько
часов, конечно. Если сможете сделать testcase для баги, было бы замечательно.
Неактивен
С тесткейсом проблема. После последних правок больших задержек не возникает. Плюс, поигрался ещё настройками майки. Было так:
innodb_buffer_pool_size - не указан
max_allowed_packet - не указан
query_cache_size - не указан
Поставил так:
innodb_buffer_pool_size=1G
max_allowed_packet=256M
query_cache_size=64M
Неактивен
Резюме: баги не было. По-умолчанию, innodb использует 8 мегабайт в буфере. Он действительно
очень медленно (в силу 8 мегабайт) пытался удалять Ваши строки (а потом откатывать транзакцию)
Раз уж решили тюнить сервер, предлагаю также подумать о
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 0
Неактивен
Обязательно попробую. Подскажите, только, пожалуйста, назначение этих переменных. Что именно изменится в работе сервера?
Неактивен
log_buffer_size - это лог транзакций в памяти. Если транзакция помещается в этот буфер целиком, то для того,
чтобы ее откатить, достаточно просто освободить этот кусок памяти. Если не помещается - будет бегать по диску
при выполнении (отмечать состояние выполнения) и потом при откатывании - тоже бегать.
flush_log - это сбрасывание лога транзакций на диск после каждой транзакции. При установке в ноль, лог
сбрасывается на диск раз в секунду, а не после каждой транзакции.
Неактивен