我正在使用MySQL作为数据库后端运行django站点。
最后我在django_session表中有3百万行。他们中的大多数都已过期,因此我想删除它们。
但如果我手动运行delete from django_session where expire_date < "2011-04-18"
整个网站似乎被绞死 - 它无法通过浏览器访问。
为什么会出现这种阻塞?如何避免呢?
答案 0 :(得分:5)
如果您的表格为MyISAM
,则DELETE
操作会锁定表格,并发查询无法访问该表格。
如果要删除的记录很多,表格会被锁定太长时间。
将您的DELETE
语句拆分为几个较短的批次。
答案 1 :(得分:1)
我不是MySQL专家,但我猜MySQL会锁定表以进行删除,这可能与MySQL事务/后端相关。当删除正在进行时,MySQL阻止从其他连接访问该表。 MyISAM和InnoDB后端行为可能有所不同。我建议你学习与此相关的MySQL手册:问题不仅限于Django域,而且一般如何删除MySQL行而不阻止访问表。
为了将来的参考,我建议你设置一个会话清理任务,它将清除会话,让我们说一天一次,从cron开始,这样你就不会得到如此巨大的表格。
答案 2 :(得分:0)
您可以尝试使用示例清理命令 - http://docs.djangoproject.com/en/dev/topics/http/sessions/?from=olddocs#clearing-the-session-table - 它会删除我认为的所有过期会话。
答案 3 :(得分:0)
如果我没记错,expire_date列上没有索引在很多行上运行需要一段时间。虽然这种情况正在发生,但它也会锁定桌面(至少在MyISAM中)。
您可能最好根据主键(例如id)删除,直到django_session表中的行数较少为止。行数较少后,可以向expire_date添加索引,并确保定期运行cleanup命令。
您必须估计从哪里开始删除,但假设您知道ID小于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;
当然你应该创建一个脚本来执行此操作。
通常,您希望一次删除较少的行。它总体上需要更长时间,但它不应该一次性锁定您的网站太久。