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千兆字节的存储空间. 您的选择包括: >覆盖表定义中的列数据类型: 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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |