PHP致命错误:允许的内存大小xxx字节耗尽PDO

时间:2017-05-18 12:34:20

标签: php mysql pdo iis-8 large-data

我遇到了一个问题,我在php 7.0.5中超出了我的内存限制, 内存限制设置为3072M

PHP Fatal error:  Allowed memory size of xxx bytes exhausted PDO

IIS服务器运行4 G Ram总计。 我正在连接远程专用的MySQL服务器。

class DB{

    private $dbh;
    private $stmt;

    public function __construct($db) {
        $host = HOST;
        $this->db = $db;
        try {
            $this->dbh = new PDO(
                "mysql:host=$host;dbname=$this->db",
                USER,
                PASS
            );          
        }catch (PDOException $e) {
            print "Error!: " . $e->getMessage() . "<br/>";
            die();
        }
    }

    public function query($query) {
        $this->stmt = $this->dbh->prepare($query);
        return $this;
    }

    public function bind($pos, $value, $type = null) {

        if( is_null($type) ) {
            switch( true ) {
                case is_int($value):
                    $type = PDO::PARAM_INT;
                    break;
                case is_bool($value):
                    $type = PDO::PARAM_BOOL;
                    break;
                case is_null($value):
                    $type = PDO::PARAM_NULL;
                    break;
                default:
                    $type = PDO::PARAM_STR;
            }
        }

        $this->stmt->bindValue($pos, $value, $type);
        return $this;
    }

    public function execute() {
        return $this->stmt->execute();
    }

    public function resultset() {
        $this->execute();
        return $this->stmt->fetchAll();
    }

    public function fetchArray() {
        $this->execute();
        return $this->stmt->fetchAll();
    }

    public function numRows() {
        $this->execute();
        return $this->stmt->rowCount();
    }

    public function single() {
        $this->execute();
        return $this->stmt->fetch();
    }

    public function insertID()
    {
        return $this->dbh->lastInsertId();
    }   
}

    function updateBooleanInRecord()
    {
        $query = "select inRecordID, recordStatus from `ems-reporting`.inrecord";
        $db = new DB("reporting");
        $db->query($query); 
        if($db->numRows() > 0){
            $out = $db->fetchArray();
            foreach($out as $output){
                if($output['recordStatus'] == "False"){
                    updateFalseRecord($output['inRecordID']);
                }
                if($output['recordStatus'] == "True"){
                    updateTrueRecord($output['inRecordID']);
                }
            }
        }
    }

    function updateFalseRecord($inRecordID){
        $query = "UPDATE `reporting`.inrecord set recordStatus = '0' where inRecordID = ?";
        $dba = new DB("ems-reporting");
        $dba->query($query);
        $dba->bind(1, $inRecordID);
        $dba->execute();
        unset($dba);
        $dba = null;
    }

    function updateTrueRecord($inRecordID){
        $query = "UPDATE `reporting`.inrecord set recordStatus = '1' where inRecordID = ?";
        $dbb = new DB("ems-reporting");
        $dbb->query($query);
        $dbb->bind(1, $inRecordID);
        $dbb->execute();
        unset($dbb);
        $dbb = null;
    }

    updateBooleanInRecord();

我从中提取的数据集包含超过3600万行数据,而我收到的错误似乎与以下内容有关:

public function execute() {
    return $this->stmt->execute();
}

到目前为止,我所做的研究表明,我应该像以下一样添加以下内容:

$this->dbh = new PDO(
                    "mysql:host=$host;dbname=$this->db",
                    USER,
                    PASS
                );

缓冲查询属性添加:

$this->dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, FALSE);

我试过这个,但请求运行了几秒钟,可能是10秒,然后只是停止,浏览器中没有显示错误或出现在日志中。所以我没有说明停止脚本的原因。在进行此添加后,内存使用量似乎根本没有增长。

在我添加上面的setAttribute之前,我打开了任务管理器来观察进程消耗内存直到达到极限,然后进程在浏览器中失败并显示以下消息:

Fatal error: Allowed memory size of 3221225472 bytes exhausted (tried to allocate 1166262464 bytes) in D:\path\to\folder\index.php on line 54

希望有人可以指出我在这里做错了什么,或者尝试找到问题的一些提示,基本上任何帮助都会非常感激。

编辑: 以下SQL语句在源头解决了我的问题,我没有想清楚。感谢你的回复,我看到fetchAll()显然不是这样做的方式,导致我遇到的问题......时间睡觉......

UPDATE `reporting`.inrecord set recordStatus=1 where recordStatus="True"

接着是

UPDATE `reporting`.inrecord set recordStatus=0 where recordStatus="False"

0 个答案:

没有答案