mysql+stmt+内存泄漏_PHP mysql_stmt :: fetch()使PHP致命错误内存耗尽

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

问题是双重的:

User variables can be assigned a value from a limited set of data types: integer, decimal, floating-point, binary or nonbinary string, or NULL value.

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

If you refer to a variable that has not been initialized, it has a value of NULL and a type of string.

前三个这些数据类型(即整数,十进制和浮点值)中的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();

>提升PHP的memory 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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值