Django:你怎么能阻止长查询杀死你的数据库?

时间:2009-08-30 06:10:05

标签: python mysql django timeout

我正在使用Django 1.1和Mysql 5. *以及MyISAM表。

我的一些查询可能需要花费大量时间来处理数据集中的异常值。这些锁定表并关闭站点。其他时候似乎有些用户在完成请求之前取消了请求,而某些查询将停留在“准备”阶段,锁定所有其他查询。

我将尝试追踪所有角落的情况,但很高兴有一个安全网,所以网站不会下降。

我该如何避免这种情况?我可以设置最长查询时间吗?

6 个答案:

答案 0 :(得分:1)

不幸的是,MySQL不允许您轻松避免这种情况。一种常见的方法基本上是编写一个脚本,每X秒检查一次所有正在运行的进程(基于你认为“长”的内容)并杀死它看到运行时间过长的进程。但是,您至少可以通过在MySQL中设置log_slow_queries来获取一些基本诊断信息,这会将所有超过10秒的查询写入日志中。如果对于您认为“慢”的目的而言太长,您可以将long_query_time设置为10以外的值来更改阈值。

答案 1 :(得分:1)

我正在做一个Django数据库复制应用程序并且具有相同的困境,如果网络延迟增加,跨WAN的查询有时似乎会挂起。

来自http://code.activestate.com/recipes/576780/

食谱576780:(几乎)任何可赎回的超时

创建任何可调用的时间限制版本。

例如,要将函数f限制为t秒, 首先创建f的限时版本。

from timelimited import *

f_t = TimeLimited(f, t)

然后,不要使用f(...),而是使用f_t之类的

try:
    r = f_t(...)
except TimeLimitExpired:
    r = ...  # timed out

以下列方式使用它:

def _run_timed_query(cursor, log_msg, timeout, query_string, *query_args):
    """Run a timed query, do error handling and logging"""
    import sys
    import traceback
    from timelimited import *

    try:
        return TimeLimited(cursor.execute, timeout)(query_string, *query_args)
    except TimeLimitExpired:
        logger_ec.error('%s; Timeout error.' % log_msg)
        raise TimeLimitExpired
    except:
        (exc_type, exc_info, tb) = sys.exc_info()
        logger_ec.error('%s; %s.' % (log_msg, traceback.format_exception(exc_type, exc_info, None)[0]))
        raise exc_type

答案 2 :(得分:0)

似乎唯一可靠的中止查询的方法是kill command。一个不太激烈的措施是关闭连接(并重新打开一个连接);这会在他们尝试send some output到客户端时立即终止查询。

答案 3 :(得分:0)

您知道查询是什么吗?也许您可以优化SQL或在表上放置一些索引?

答案 4 :(得分:0)

使用InnoDB表,它们row-locking代替table-locking

答案 5 :(得分:0)

您不应该编写类似的查询,至少不要针对您的实时数据库运行。 Mysql有一个“慢查询”参数,你可以用它来识别杀死你的查询。大多数情况下,这些慢速查询要么是错误的,要么可以通过定义一个或两个新索引来加速。