PHP mysql_stmt :: fetch()使PHP致命错误内存耗尽

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了PHP mysql_stmt :: fetch()使PHP致命错误内存耗尽脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
CentOS 6.4 PHP 5.3.3 MysqL 5.1.69 x86_64

MysqL_stmt::fetch()

当使用预准备语句执行fetch时,PHP会产生错误PHP致命错误:允许的内存大小为134217728字节耗尽(尝试分配4294967296字节).

当用于创建临时表的SELECT语句中包含的变量未设置时,无论是否调用存储过程之前在环境中设置该变量,都会发生这种情况.必须在存储过程中设置变量.当SELECT语句用于将临时表中的数据返回给PHP,并且PHP使用MysqL_stmt :: fetch()来访问数据时,PHP生成上述致命错误.

MysqL代码

DELIMITER $$
CREATE PROCEDURE test_sp()
BEgin

    # uncomment below line,and PHP call to MysqLi_stmt::fetch() works
    # SET @status = 1;

    # remove tmp table
    DROP TABLE IF EXISTS tmp_table;
    # CREATE TEMPORARY TABLE
    CREATE TEMPORARY TABLE tmp_table
        SELECT @status AS status;

    SELECT * From tmp_table;

END $$
DELIMITER ;

PHP代码

// oBTain MysqL LOGin info
require_once(MysqLOBJ);

// initialize status
$status = "";


$db = new MysqLi(
    DB_HOST,DB_USER,DB_PASSWORD,DB_NamE
    );


$query = "CALL test_sp";

$stmt = $db->prepare($query);

$stmt->execute();

$stmt->bind_result( $status );

$stmt->Store_result();

$stmt->fetch(); // PHP Fatal error OCCURS HERE

$stmt->free_result();

$db->close();

print "<p>status = $status</p>\n";

解决方法

您会发现仅当@status为NULL或字符串时才会发生这种情况.

问题是双重的:

>与local variables不同,MysqL user variables支持一组非常有限的数据类型:

文档没有提到使用的actual datatypes分别是BigINT,DECIMAL(65,30),DOubLE,LONGBLOB,LONGTEXT和LONGBLOB.关于最后一本,手册至少解释了:

前三个这些数据类型(即整数,十进制和浮点值)中的Storage分别需要8,30和8个字节.其他数据类型(即字符串和NULL值)需要(最多)4千兆字节的存储空间.
>由于您使用的是v5.4.0之前的PHP版本,因此认的MysqL驱动程序是libmysql,在数据绑定时只有服务器可以使用列类型元数据 – 因此MysqLi尝试分配足够的内存来保存每个可能的值(即使最终没有要求完整的缓冲区);因此,NULL和字符串值的用户变量(最大可能的大小为4GiB)会导致PHP超过其认内存限制(自PHP v5.2.0起为128MiB).

您的选择包括

>覆盖表定义中的列数据类型:

DROP TEMPORARY TABLE IF EXISTS tmp_table;
CREATE TEMPORARY TABLE tmp_table (
  status VArchAR(2)
) SELECT @status AS status;

>将用户变量显式为casting更具体的数据类型:

DROP TEMPORARY TABLE IF EXISTS tmp_table;
CREATE TEMPORARY TABLE tmp_table
  SELECT CAST(@status AS CHAR(2)) AS status;

>使用使用显式数据类型声明的局部变量:

DECLARE status VARCHAR(2) DEFAULT @status;
DROP TEMPORARY TABLE IF EXISTS tmp_table;
CREATE TEMPORARY TABLE tmp_table
  SELECT status;

>通过调用MysqLi_stmt :: store_result()before MysqLi_stmt :: bind_result()解决此问题,这会导致结果集存储在libMysqL中(超出PHP的内存限制),然后PHP将仅分配保存所需的实际内存获取时记录:

$stmt->execute();
$stmt->store_result();
$stmt->bind_result( $status );
$stmt->fetch();

>提升PHPmemory limit以便它可以容纳4GiB缓冲区的分配(尽管应该知道这样做会对硬件产生影响) – 例如,完全消除内存限制(尽管意识到潜在的负面影响)从这样做,例如从真正的内存泄漏):

ini_set('memory_limit','-1');

>重新编译PHP,配置为使用the native mysqlnd driver(自v5.3.0起包含在PHP中,但在PHP v5.4.0之前未配置为认值)而不是libMysqL

./configure --with-MysqLi=MysqLnd

>升级PHP v5.4.0或更高版本,以便认使用MysqLnd.

脚本宝典总结

以上是脚本宝典为你收集整理的PHP mysql_stmt :: fetch()使PHP致命错误内存耗尽全部内容,希望文章能够帮你解决PHP mysql_stmt :: fetch()使PHP致命错误内存耗尽所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。