今天遇到一个问题,在适用lararl跑脚本对老师的作息表进行拆分(一个6000多行的表拆分后带个300万行)时,发现随着脚本的运行,内存的使用量在不断增加,cpu的占用也随之在不断的增加。最后因为内存不够用而中断退出。
一开始的想可能是因为内存不够用,所以在脚本前面加入ini_set('memory_limit', '512M'); 发现内存还是不够用,又增加到1024M,2048M...,最后也没有解决问题,内存占用到50%多的时候依然会挂掉,我们的开发机是2核4G的阿里云ECS,这样不断加内存的方法显然是不行的,因为操作系统的剩余内存是有限的。
后来想,可能是数组在插入到数据库后没有unset掉,造成内存溢出。所以尝试,每次插入数组后unset掉,依然没有解决内存占用过高的问题。
最后想到,有可能是因为数据库连接的问题,在脚本执行的过程中,PDO连接一直被占用,没有被释放。随着数据量的不断增加,PDO连接需要处理的数据量一直在增加。所需要的内存也会一直增加。
按照这个思路,可以在处理完一部分数据时(比如拆分完200行时),可以断开一下PDO连接,然后重连一次,这样可以释放一次内存。
laravel里面有关数据库连接的方法在vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php中,disconnect()可以断开PDO连接,reconnect()断开连接后重连,但是这两个方法都是只断开不会释放连接,当再次连接时,直接从 $this->connections数组中取出来。purge()断开连接后,会将他从$this->connections中unset掉,释放内存。看来就是这个方法了。
\DB::connection()->enableQueryLog(); $result = \DB::select('select * from activity'); $log = \DB::getQueryLog(); dd($log); \error_log('$log = ' . print_r($log, true) . "\n", 3, "/tmp/error.log");
public function utf8_urldecode($str) { if(strpos('+'.$str,'%u')>0) { $str = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($str)); return html_entity_decode($str,null,'UTF-8');; } else if(strpos('+'.$str,'%')) { return urldecode($str); } else { return $str; } }
今天用多贝云的API上传课件时,报了如下的错误,这个是是在PHP5.5中出现的问题,原来是PHP5.5废弃了’@’这种模式。
The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead
PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。
传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:
curl_setopt(ch, CURLOPT_POSTFIELDS, array( 'file' => '@'.realpath('image.png'), )); equals $ curl -F "file=@/absolute/path/to/image.png"
PHP 5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。
解决方法:
对上传文件调用curl_file_create()创建CURLFile,代码如下:
public function uploadDocument($filename) { $params = $this->prepareParameters(array()); #$params["slidesFile"] = "@" . $filename; $params['slidesFile'] = curl_file_create($filename);//使用这种方式 $path = "/api/v3/documents/upload"; $result = $this->post($path, $params); return $result; }
/* *功能:对字符串进行加密处理 *参数一:需要加密的内容 *参数二:密钥 */ function passport_encrypt($str,$key){ //加密函数 srand((double)microtime() * 1000000); $encrypt_key=md5(rand(0, 32000)); $ctr=0; $tmp=''; for($i=0;$i<strlen($str);$i++){ $ctr=$ctr==strlen($encrypt_key)?0:$ctr; $tmp.=$encrypt_key[$ctr].($str[$i] ^ $encrypt_key[$ctr++]); } return base64_encode(passport_key($tmp,$key)); } /* *功能:对字符串进行解密处理 *参数一:需要解密的密文 *参数二:密钥 */ function passport_decrypt($str,$key){ //解密函数 $str=passport_key(base64_decode($str),$key); $tmp=''; for($i=0;$i<strlen($str);$i++){ $md5=$str[$i]; $tmp.=$str[++$i] ^ $md5; } return $tmp; } /* *辅助函数 */ function passport_key($str,$encrypt_key){ $encrypt_key=md5($encrypt_key); $ctr=0; $tmp=''; for($i=0;$i<strlen($str);$i++){ $ctr=$ctr==strlen($encrypt_key)?0:$ctr; $tmp.=$str[$i] ^ $encrypt_key[$ctr++]; } return $tmp; }