2010-02-13 4 views
7

Я пытаюсь найти способ сделать условный DELETE на таблице InnoDB, которая содержит миллионы записей, не блокируя ее (таким образом, не доводя сайт вниз).Удаление из таблицы с миллионами записей

Я попытался найти информацию о mysql.com, но безрезультатно. Любые советы о том, как действовать?

+0

Есть много индексов на этой таблице? –

+0

Укажите столбцы, которые будут обрабатывать условия. Затем выполните удаление, когда трафик на сайт низкий (возможно, @ ночь). – 2010-02-13 14:54:40

+0

см. Также http://stackoverflow.com/questions/23193761/delete-operation-locks-whole-table-in-innodb, который упоминает блокировку зазора – rogerdpack

ответ

8

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

Я нашел некоторую информацию по этому вопросу здесь: http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html

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

START TRANSACTION; 

DELETE FROM tab WHERE id = 1; 
.. 
.. 
DELETE FROM tab WHERE id = x; 

COMMIT; 

Вы можете создавать необходимые statments делать что-то вроде

SELECT CONCAT('DELETE FROM tab WHERE id = ', id) 
FROM tab 
WHERE <some intricate condition that selects the set you want to delete> 

поэтому преимущество над этим методом вместо делать:

DELETE FROM tab 
WHERE <some intricate condition that selects the set you want to delete> 

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

+0

+1, перспективное решение! Вы когда-нибудь использовали этот подход на практике? – Frunsi

+0

@frunsi: Честно признаюсь, что я этого не сделал.Как правило, у меня нет большой проблемы с удалением миллиона строк, но опять же системы, которыми я управляю, не пострадают от многих пользователей одновременно. –

5

Если это подходит вашему приложению, вы можете ограничить количество удаляемых строк и настроить cronjob для повторения удаления. Например:

DELETE FROM tab WHERE .. LIMIT 1000 

Я нашел, что это хороший компромисс в аналогичном сценарии.

+0

Я думаю, что проблема с этим подходом заключается в том, что LIMIT оценивается после выделения набора , Таким образом применяется 'WHERE', который может блокировать строки, которые находятся в том же диапазоне, что и строки, которые вы удаляете. Тот факт, что вы удаляете только ограниченное число, не меняет того факта, что записи уже заблокированы. Что этот метод делает, так это держать размер транзакции небольшим, что тоже хорошо. Насколько я понимаю, это не предотвращает ложную блокировку. –

+0

@ Роланд: Вы можете быть правы. Это решение может быть не идеальным, но отлично работает на практике (ограниченное удаление выполняется быстро, поэтому блокировки сохраняются для очень малых временных интервалов, предельный параметр может быть настроен на реальные данные о жизни). Я использовал некоторые тесты, прежде чем использовать этот подход, и накопленное время всех ограниченных удалений закончилось за меньшее время, чем один неограниченный (но в это время он использовал таблицы MySQL 3.x и MyISAM). Он по-прежнему работает, но в тестах на текущие таблицы MySQL и InnoDB можно было бы немного освежить детали. – Frunsi

+0

да, я думаю, можно с уверенностью сказать, что описанный вами сценарий - блокировка MyISAM-сервера на более чем 9-летней версии продукт по сравнению с движком InnoDB, в котором реализованы как многоуровневое управление параллелизмом, так и блокировка на уровне строк, действительно может быть несколько иной: p –

Смежные вопросы