0

我正在使用TCPDF即时创建 PDF 文档。生成这些 PDF 的一些查询包含超过 1,000 条记录,并且我的服务器因更大的查询而超时(内部服务器错误)。我正在使用 PHP 和 MySQL。

如何使用 AJAX 将大型 MySQL 查询解析为较小的块、缓存数据并重新组合结果,以防止服务器超时?

这是我当前的代码:

require_once('../../libraries/tcpdf/tcpdf.php');

$pdf = new TCPDF();

$prows = fetch_data($id);

$filename = '../../pdf_template.php';

foreach ($prows AS $row) {

    $pdf->AddPage('P', 'Letter'); 
    ob_start(); 

    require($filename);

    $html .= ob_get_contents();
    ob_end_clean();

    $pdf->writeHTML($html, true, false, true, false, '')

}

$pdf->Output('documents.pdf', 'D');
4

2 回答 2

0

如果每次调用时都必须生成数据,您可以将查询分成 100 行的块,将数据缓存在文件系统上(或者,更好的是,在 APC/WinCache/XCache/MemCache 中)然后在最终的 AJAX 调用 (Finalquery=true) 上,加载缓存、生成 PDF 并清除缓存。

我假设您无法更改脚本的最大运行时间,例如<?php set_time_limit(0);

流程是这样的:

  • 为查询操作生成唯一 ID
  • 在客户端,通过对 php 脚本的初始调用(选择计数...等)获取最大行数。
  • 然后,将其除以 10、100、1000,无论您想将其分成多少个请求。
  • 为每个具有唯一 ID 的块(第 0、100、100,200 行)运行 AJAX 请求。
  • 在服务器端,您选择该行数/选择的行,并将其放入某处的存储中。我熟悉 WinCache(我一直在 Windows 上开发 PHP ......),所以将它添加到用户缓存中:wincache_ucache_add( $uniqueId . '.chunk' . $chunkNumber, $rows);
  • 同时,在客户端,跟踪所有 AJAX 请求。当每一个都完成后,调用生成 PDF 函数服务器端。给出块的数量和唯一的 id。
  • 在服务器端,从缓存中获取所有内容。$rows = array_merge( wincache_ucache_get($uniqueId . '.chunk'. $chunkNumber1), wincache_ucache_get($uniqueId . '.chunk'. $chunkNumber2) );
  • 清除缓存:wincache_ucache_clear();
  • 生成 PDF 并返回。

请注意,您实际上应该只缓存查询结果,无论是手动还是通过抽象层或 ORM 中的功能。

于 2012-06-26T02:04:01.577 回答
0

尝试像 PEAR cache_lite 这样的简单缓存。在缓慢或关闭期间,您可以创建一个实用程序来运行和缓存您需要的所有记录。然后,当用户请求 PDF 时,您可以访问您的缓存数据,而无需访问您的数据库。此外,您可以只使用表上的时间戳字段并请求自缓存数据以来已更改的数据库记录,这将显着降低您必须从数据库中实时检索的当前记录数。

<?php
include 'Cache/Lite/Output.php';
$options = array(
    'cacheDir' => '/tmp/cache/',
    'lifeTime' => 3600,
    'pearErrorMode' => CACHE_LITE_ERROR_DIE,
    'automaticSerialization' => true
);

$cache = new Cache_Lite_Output($options);
if( $data_array = $cache->get('some_data_id') ) {
    $prows = $data_array;
} else {
    $prows = fetch_data($id);
    $cache->save($prows);
}

print_r($prows);

?>
于 2012-06-26T13:55:27.457 回答