MySQL и django зависают при удалении огромной сессии

#python #mysql #django

#python #mysql #django

Вопрос:

Я запускаю сайт django с MySQL в качестве серверной части базы данных. Наконец, у меня есть 3 миллиона строк в таблице django_session. Срок действия большинства из них истек, поэтому я хочу их удалить. Но если я запускаю вручную delete from django_session where expire_date < "2011-04-18" , кажется, что весь сайт зависает — к нему невозможно получить доступ через браузер.

Почему возможен такой вид блокировки? Как этого избежать?

Ответ №1:

Если ваша таблица MyISAM , DELETE операции блокируют таблицу, и она недоступна для параллельных запросов.

Если требуется удалить много записей, таблица заблокирована слишком надолго.

Разделите свой DELETE оператор на несколько более коротких пакетов.

Ответ №2:

Я не эксперт по MySQL, но я предполагаю, что MySQL блокирует таблицу для удаления, и это может быть связано с транзакцией MySQL / серверной частью. Когда выполняется удаление, MySQL блокирует доступ к таблице из других подключений. Поведение серверной части MyISAM и InnoDB может отличаться. Я предлагаю вам изучить руководство по MySQL, связанное с этим: проблема не ограничивается доменом Django, но в целом, как удалить строки MySQL, не блокируя доступ к таблице.

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

Комментарии:

1. Да, в будущем не позволяйте этому расти так сильно. Существует команда управления, которую вы можете периодически запускать (возможно, с помощью cron), которая удалит строки с истекшим сроком действия.

Ответ №3:

Вы могли бы попробовать пример команды очистки — http://docs.djangoproject.com/en/dev/topics/http/sessions/?from=olddocs#clearing-the-session-table — который удаляет все сеансы с истекшим сроком действия, я думаю.

Ответ №4:

Если я правильно помню, в столбце expire_date нет индекса Работа с большим количеством строк займет некоторое время. Пока это происходит, это также сохранит блокировку таблицы (по крайней мере, в MyISAM).

Возможно, вам было бы лучше удалять на основе первичного ключа (например, id), пока у вас не останется меньше строк в таблице django_session. Как только у вас останется меньше строк, вы можете добавить индекс в expire_date и убедиться, что вы регулярно запускаете команду cleanup.

Вам нужно будет оценить, с чего начать удаление, но предполагая, что вы знаете, что все строки с идентификатором менее 2 900 000 нуждаются в удалении:

 
delete from django_session where id < 29000000;
  

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

 
begin;
delete from django_session where id < 10000;
commit;
begin;
delete from django_session where id < 20000;
commit;
...
begin;
delete from django_session where id < 29000000;
commit;
  

Конечно, вам, вероятно, следует создать скрипт для этого.

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