2010-05-14 141 views
8

我有一个运行相当多的数据库查询的PHP网站。通过某些参数组合,这些查询最终可能会运行很长时间,从而触发一个丑陋的超时消息。我想根据我的站点样式的其余部分用主题很好的超时消息替换它。如何让PHP脚本在等待长时间运行的MySQL查询时正常超时?

预见通常回答这样一个问题:

  1. “优化你的查询,使他们不这么长时间运行” - 我记录长时间运行的查询和优化他们,但只有我在用户受到影响后了解这些信息。

  2. “增加您的PHP超时设置(例如,set_time_limit,max_execution_time),以便长时间运行的查询可以完成” - 有时查询可以运行几分钟。我想告诉用户在这之前有问题(例如30秒后)。

  3. “使用register_tick_function监视脚本运行了多长时间” - 这仅在脚本中的代码行之间执行。当脚本正在等待数据库的响应时,tick函数不会被调用。

万一有帮助,该网站是使用Drupal的(有很多定制的)所建,是一个虚拟专用Linux服务器上使用MySQL 5上运行PHP 5.2

回答

0

connection handling文档是什么你需要。

基本上,您需要使用register_shutdown_function()注册关闭功能。无论脚本是否成功完成,用户已取消(ESC键)还是超时,脚本完成后都会调用此函数。

该关闭功能可以调用connection_status()功能。如果connection_status()返回2(TIMEOUT)并且上一页是运行棘手查询的页面,则可以将用户重定向到一个页面,说“对不起,但我们现在正在经历高服务器负载。”或其他。

+0

这只涉及到运行php代码的地方(通常是一个web服务器)和浏览器之间的连接 - 而不是web服务器和DBMS – symcbean 2010-05-14 12:00:41

+0

他没有要求与DBMS通信的东西,只是一种处理脚本超时的机制优雅地说,这就是connection_status()的设计目的。我编辑了我的答案以提供更多信息。 – Mathew 2010-05-14 16:16:19

+0

这听起来像我需要的解决方案,但我正在努力与重定向。我正在尝试使用PHP header()函数,但它表示标题已经发送。即使有一个简单的测试用例: 'set_time_limit(1); register_shutdown_function( 'clean_shutdown');' 而(真){ } 功能clean_shutdown(){ 如果(CONNECTION_STATUS()&CONNECTION_TIMEOUT){ ob_end_clean(); header('Location:http://www.bbc.co.uk',TRUE,500); } } 我仍然收到一个“头文件已经发送(在第5行)”的消息,但是我看不到它们会被发送到哪里。 – 2010-05-17 09:43:33

3

没有异步的mysql调用,也没有分叉轻量级线程的范围。

尽管可以将PHP代码拆分为两层,并使用可以异步调用的连接,但这种方法的问题在于数据库层在上层服务器放弃之后仍尝试运行查询获得结果 - 可能会阻止其他用户的DBMS。 (你更有可能更频繁地请求页面超时)。

如果将超时处理推入位于Web服务器前的反向代理,则会出现同样的问题。

实现超时最明智的地方是数据库本身 - 但AFAIK,MySQL不支持。

因此,下一个选项是在PHP和数据库之间建立一个代理 - 这可以是自包含的 - 为每个请求生成2个轻量级线程(1运行查询,第二个作为监视器杀死第一个太长) - 但这不仅需要以支持轻量级线程的语言编写代码,还需要定义与PHP通信的协议。

但是采取不同的方法来处理代理模型 - 您可以使用proc_open产生一个单独的PHP进程,并将stdout流设置为非阻塞 - 这样PHP可以继续运行并检查代理是否有运行查询。如果它超时,那么作为代理的父代,它可以发信号通知它关闭(proc_terminate()),这应该停止查询在数据库上运行。

当然,这将意味着很多开发工作。

设置一个或多个从属DBMS来运行您的慢速查询可能会证明更简单 - 可能会带来智能负载平衡。或者查看其他方式让慢速查询变得更快 - 就像预合并一样。

HTH

C.

0

是您的服务器调整与APC,内存缓存,加速和Drupal缓存?那些替代路线工作得很好。

否则,在Drupal中会运行什么类型的脚本会导致这种情况?出于好奇,你正在运行视图和面板?

+0

这不是一个Drupal问题。我们正在使用视图和面板,但不在网站的这一部分。 (我知道这些模块仍然会被加载,但我们没有给它们打电话)。这里的问题仅限于数据库访问,而这是导致问题的客户特定查询。有些客户比其他客户拥有更多的数据,有些客户要求比其他客户更长的时间。我已经创建了汇总表来加快许多查询,但仍有工作要做。我正在寻找一些能够在工作正在进行时提供更清晰的用户体验的产品。 – 2010-05-17 07:29:51