zoukankan      html  css  js  c++  java
  • 【nodejs】FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed

    当使用大批量(>100)的SQL进行MySql数据库插值任务时,会发生以下错误:

    总计将有371579条数据将被插入数据库
    开始插入DB
    
    <--- Last few GCs --->
    
    [12416:000001BE7F7E63A0]    81278 ms: Mark-sweep 1410.0 (1443.8) -> 1410.0 (1443.8) MB, 1911.9 / 0.0 ms  last resort
    
    
    <--- JS stacktrace --->
    
    ==== JS stack trace =========================================
    
    Security context: 000000C777FA8799 <JSObject>
        2: createQuery [C:Usershorn1Desktop
    ode.js66-??????1.09 - insertdb.js
    ode_modulesmysqllibConnection.js:64] [bytecode=000002482E476A59 offset=166](this=000000F8C033D3E1 <JSFunction Connection (sfi = 000002A3CFFB6579)>,sql=000002A3CFFADB71 <String[101]: insert into test.topic17(floor,author,tdate,ttime,addtime,url,title,content) values (?,?,?,?,?,?,?,?)>,values=00000245428FEC61 <JSA...
    
    FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
    
    C:Usershorn1Desktop
    ode.js66-理想论坛爬虫1.09 - insertdb.js>

    因为插入的数据有37万条之多,无论使用下面哪种程序都会导致这样的结果:

    插入代码1:

    //======================================================
    // 在理想论坛帖子下载爬虫生成数据文件后读取数据插入数据库
    // 2018年5月6日
    //======================================================
    var fs=require('fs');    // 内置文件处理模块
    var allfiles=[];        // 全部数据文件列表
    var allInfos=[];        // 数据文件里获得的全部信息
    
    //--------------------------------------
    // 将数据插入数据库
    //--------------------------------------
    function insertDB(){
        console.log("开始插入DB");
        //console.log('总计将有'+allInfos.length+"条数据将被插入数据库");
        
        var mysql=require('mysql'); // 连接mysql数据库的模块
    
        var conn=mysql.createConnection({
            host:'127.0.0.1',
            port:'3306',
            database:'test',
            user:'root',
            password:'12345678',
        });
    
        conn.connect(function(err){
            if(err){
                console.log('与MySQL数据库建立连接失败');
            }else{
                console.time('插数据花费时间');
    
                for(var i=0;i<allInfos.length;i++){
                    var info=allInfos[i];
                    sql='insert into test.topic17(floor,author,tdate,ttime,addtime,url,title,content) values (?,?,?,?,?,?,?,?)';
                    arr=[info['楼层'],info['作者'],info['日期'],info['时间'],currTime(),info['url'],info['title'],info['内容']];
    
                    conn.query(sql,arr,function(err,result){
                        if(err){
                            console.log("出现异常:"+err+",此时info="+info);
                        }
                    })
                }
    
                //conn.end();
                console.timeEnd('插数据花费时间');
            }
        }); 
    }
    
    //--------------------------------------
    // 通用函数,返回当前日期时间 数据库记录时间用
    //--------------------------------------
    function currTime() {
        var date = new Date();
        var seperator1 = "-";
        var seperator2 = ":";
        var month = date.getMonth() + 1;
        var strDate = date.getDate();
        if (month >= 1 && month <= 9) {
            month = "0" + month;
        }
        if (strDate >= 0 && strDate <= 9) {
            strDate = "0" + strDate;
        }
        var currentdate =date.getFullYear() + seperator1 + month + seperator1 + strDate
                + " " + date.getHours() + seperator2 + date.getMinutes()
                + seperator2 + date.getSeconds()+ " ";
        return currentdate;
    }
    
    //-------------------------------
    // 得到带颜色(前景色)的文字,用于在控制台输出
    // text:文字,color:前景色
    //-------------------------------
    function coloredText(text,color){
        var dic = new Array();
    
        dic["white"] = ['x1B[37m', 'x1B[39m'];
        dic["grey"] = ['x1B[90m', 'x1B[39m'];
        dic["black"] = ['x1B[30m', 'x1B[39m'];
        dic["blue"] = ['x1B[34m', 'x1B[39m'];
        dic["cyan"] = ['x1B[36m', 'x1B[39m'];
        dic["green"] = ['x1B[32m', 'x1B[39m'];
        dic["magenta"] = ['x1B[35m', 'x1B[39m'];
        dic["red"] = ['x1B[31m', 'x1B[39m'];
        dic["yellow"] = ['x1B[33m', 'x1B[39m'];
    
        return dic[color][0]+text+dic[color][1];
    }
    
    function readFiles(){
        if(allfiles.length>0){
            var file=allfiles.pop();
    
            fs.readFile(file,'utf8',function(err,data){
                if(err){
                    console.log('读取文件失败,因为'+err);
                }else{
                    var infos=JSON.parse(data);
                    allInfos=allInfos.concat(infos);   
                }
    
                readFiles();
            });
        }else{
            console.log('总计将有'+allInfos.length+"条数据将被插入数据库");
            insertDB();
        }
    }
    
    //--------------------------------------
    // 入口函数
    //--------------------------------------
    function main() {
        folder='./test';// 数据文件所在目录
    
        fs.readdir(folder,function(err,files){
            if(err) throw err;
            
            // 预制查找数组
            var arr=new Array(100-1);// 20563是总文件个数,从lixiang.js的输出可以找到,-1因为文件序号从0起
            for(var i=0;i<arr.length;i++){
                arr[i]=0;
            }
    
            // 只遍历一遍
            for(var index in files){
                var arrTmp=files[index].split(".");
                var sn=parseInt(arrTmp[0],10);
                arr[sn]=1;
    
                allfiles.push(folder+'/'+files[index]);
            }
    
            // 查哪个缺失
            var missed=0;
            for(var i=0;i<arr.length;i++){
                if(arr[i]==0){    // 为零的就是没找到该编号对应的文件的
                    console.log(coloredText('编号为'+i+'的文件缺失','yellow'));
                    missed++;
                }
            }
            console.log(coloredText('总计有'+missed+'个文件缺失','red'));
    
            readFiles();
        });    
    }
    
    // 开始
    main();

    插入代码2:

    //======================================================
    // 在理想论坛帖子下载爬虫生成数据文件后读取数据插入数据库
    // 2018年5月6日
    //======================================================
    var fs=require('fs');    // 内置文件处理模块
    var allfiles=[];        // 全部数据文件列表
    var allInfos=[];        // 数据文件里获得的全部信息
    
    //--------------------------------------
    // 将数据插入数据库
    //--------------------------------------
    function insertDB(){
        console.log("开始插入DB");
        //console.log('总计将有'+allInfos.length+"条数据将被插入数据库");
        
        var mysql=require('mysql'); // 连接mysql数据库的模块
    
        var pool=mysql.createPool({
            host:'127.0.0.1',
            port:'3306',
            database:'test',
            user:'root',
            password:'12345678',
            connectionLimit:10,
        });
    
            pool.getConnection(function(err,conn){
                        console.time('插数据花费时间');
                        for(var i=0;i<allInfos.length;i++){
                            var info=allInfos[i];
                            sql='insert into test.topic17(floor,author,tdate,ttime,addtime,url,title,content) values (?,?,?,?,?,?,?,?)';
                            arr=[info['楼层'],info['作者'],info['日期'],info['时间'],currTime(),info['url'],info['title'],info['内容']];
    
                            conn.query(sql,arr,function(err,result){
                                if(err){
                                    console.log("出现异常:"+err+",此时info="+info);
                                }
                            })
                        }
    
                        console.timeEnd('插数据花费时间');
    
                        conn.close();
                    
            });
    
     
    }
    
    //--------------------------------------
    // 通用函数,返回当前日期时间 数据库记录时间用
    //--------------------------------------
    function currTime() {
        var date = new Date();
        var seperator1 = "-";
        var seperator2 = ":";
        var month = date.getMonth() + 1;
        var strDate = date.getDate();
        if (month >= 1 && month <= 9) {
            month = "0" + month;
        }
        if (strDate >= 0 && strDate <= 9) {
            strDate = "0" + strDate;
        }
        var currentdate =date.getFullYear() + seperator1 + month + seperator1 + strDate
                + " " + date.getHours() + seperator2 + date.getMinutes()
                + seperator2 + date.getSeconds()+ " ";
        return currentdate;
    }
    
    //-------------------------------
    // 得到带颜色(前景色)的文字,用于在控制台输出
    // text:文字,color:前景色
    //-------------------------------
    function coloredText(text,color){
        var dic = new Array();
    
        dic["white"] = ['x1B[37m', 'x1B[39m'];
        dic["grey"] = ['x1B[90m', 'x1B[39m'];
        dic["black"] = ['x1B[30m', 'x1B[39m'];
        dic["blue"] = ['x1B[34m', 'x1B[39m'];
        dic["cyan"] = ['x1B[36m', 'x1B[39m'];
        dic["green"] = ['x1B[32m', 'x1B[39m'];
        dic["magenta"] = ['x1B[35m', 'x1B[39m'];
        dic["red"] = ['x1B[31m', 'x1B[39m'];
        dic["yellow"] = ['x1B[33m', 'x1B[39m'];
    
        return dic[color][0]+text+dic[color][1];
    }
    
    function readFiles(){
        if(allfiles.length>0){
            var file=allfiles.pop();
    
            fs.readFile(file,'utf8',function(err,data){
                if(err){
                    console.log('读取文件失败,因为'+err);
                }else{
                    var infos=JSON.parse(data);
                    allInfos=allInfos.concat(infos);   
                }
    
                readFiles();
            });
        }else{
            console.log('总计将有'+allInfos.length+"条数据将被插入数据库");
            insertDB();
        }
    }
    
    //--------------------------------------
    // 入口函数
    //--------------------------------------
    function main() {
        folder='./2018-05-05 9_8_49';// 数据文件所在目录
    
        fs.readdir(folder,function(err,files){
            if(err) throw err;
            
            // 预制查找数组
            var arr=new Array(23000-1);// 20563是总文件个数,从lixiang.js的输出可以找到,-1因为文件序号从0起
            for(var i=0;i<arr.length;i++){
                arr[i]=0;
            }
    
            // 只遍历一遍
            for(var index in files){
                var arrTmp=files[index].split(".");
                var sn=parseInt(arrTmp[0],10);
                arr[sn]=1;
    
                allfiles.push(folder+'/'+files[index]);
            }
    
            // 查哪个缺失
            var missed=0;
            for(var i=0;i<arr.length;i++){
                if(arr[i]==0){    // 为零的就是没找到该编号对应的文件的
                    console.log(coloredText('编号为'+i+'的文件缺失','yellow'));
                    missed++;
                }
            }
            console.log(coloredText('总计有'+missed+'个文件缺失','red'));
    
            readFiles();
        });    
    }
    
    // 开始
    main();

    究其原因,应该是数据库并发数有限,有太多的回调来不及执行而堆积起来造成的堆缺乏存储空间。

     这是关于此问题的一些讨论 https://cnodejs.org/topic/500904be4764b72902d30f4d

    2018年5月7日

  • 相关阅读:
    xhr
    原生js的博客
    webstorm调试Node的时候配置
    multiparty
    bluebird
    Nodejs+express+angularjs+mongodb
    mustache.js
    ModelProxy 前端接口配置建模框架
    浏览器跨域访问解决方案
    前端性能优化补充篇
  • 原文地址:https://www.cnblogs.com/heyang78/p/9000749.html
Copyright © 2011-2022 走看看