Node / MySQL - код: «ER_PARSE_ERROR», при попытке вставить ~ 800 записей

0

Я работаю над небольшой идеей, чтобы собирать ошибки со страниц и хранить их в БД, а затем использовать графический API для визуального отображения информации.

Существует 8 сайтов, и на каждом из них есть 100 записей - так 800 транзакций за раз. Я прохожу через каждый сайт, а затем подцифровываю таблицу ошибок и собираю их.

Я получил его работу, если я делаю запрос на вставку для каждой из этих суб-циклов для всех 800 записей, но я получаю утечку памяти из-за большого количества транзакций и через несколько минут - разрыв узлов из-за превышения памяти.

Поэтому я попытался поставить в очередь все 800 записей в Array of Arrays, а затем выполнить мульти-вставку в конце каждой итерации, но я получаю ER_PARSE_ERROR.

var tabletojson = require('tabletojson');
var mysql = require("mysql");
var striptag = require("striptags");
var fs = require("fs");
var path = require('path');

var startCollector;
var iterations = 0;
var insertions = 0;
var duplicated = 0;

var datas = [];

var clients = ["ClientA", "ClientB", "ClientC", "ClientD", "ClientE", "ClientF", "ClientG", "ClientH"];
var appDir = path.dirname(require.main.filename);

var errorList = ["err1", "err2", "err3", "err4", "err5", "err6"];

var con = mysql.createPool({
    host: "localhost",
    user: "User",
    password: "Password",
    database: "errors"
  });

function CollectErrors() {
    startCollector = new Date();
    for(var a = 0; a < clients.length; a++) {
        (function(a) {
            tabletojson.convertUrl("http://example.com" + clients[a] + "/page.php?limit=100", { stripHtmlFromCells: false }, function(response) {
            var rs = response[0];
                for(var l = rs.length-1; l > -1; l--) {
                    var newDate = formatDate(striptag(rs[l]["Date"]), striptag(rs[l]["Time"]));
                    var user = getUser(striptag(rs[l]["User"]));
                    var msg = striptag(rs[l]["Error"]);
                    var splitError = rs[l]["Error"].split("<a href=\"");
                    var link = getUrl(splitError[1]);
                    var id = getId(link);
                    var type = getType(striptag(splitError[0]));
                    var temp = [newDate, link, type, user, clients[a], id, msg];
                    datas.push(temp);
                }
                });
        })(a);
    }
    con.getConnection(function(err, connection) {
        connection.query("INSERT IGNORE INTO entries (time, url, type, author, client, uid, message) VALUES ?", [datas], function(err, rows) {
            console.log(err);
        });
        connection.release();
        datas = [];
    });
    setTimeout(CollectErrors, 10000);

}



function formatDate(date, time) {
    var newdate = date.split("/").reverse().join("-");
    var newtime = time+":00";
    return newdate + " " + newtime;
}

function getUrl(uri) {
    return "http://example.com/"+uri.split("\">Details")[0];
}

function getId(url) {
    return decodeURIComponent((new RegExp('[?|&]' + "id" + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}

function getType(error) {
    for(var a = 0; a < errorList.length; a++) {
        if(error.indexOf(errorList[a]) !== -1) {
            return errorList[a];
        }
    }
    return "Other";
}

function getUser(user) {
    if(user == "" || user == "&#xA0;" || user == null) {
        return "System";
    }
    return user;
}


CollectErrors();

Я тоже пробовал mysql.createConnection, но это также дало мне такую же проблему.

Я застрял в течение последних 12 часов, и я не вижу, что случилось, я даже попытался заполнить таблицу Datas целыми строками, но получил такую же ошибку.

1 ответ

2
Лучший ответ

Я изменил свой код, чтобы использовать ES6 и исправлять возможности модулей.
Полезные ссылки: правильный пул с mysql, правильный запрос вставки, async/await, IIFE, расширенный объект

const tabletojson = require('tabletojson'),
  mysql = require("mysql"),
  striptag = require("striptags"),
  fs = require("fs"),
  path = require('path');

const startCollector,
  iterations = 0,
  insertions = 0,
  duplicated = 0;

let datas = [];

const clients = ["ClientA", "ClientB", "ClientC", "ClientD", "ClientE", "ClientF", "ClientG", "ClientH"];
const appDir = path.dirname(require.main.filename);

const errorList = ["err1", "err2", "err3", "err4", "err5", "err6"];

const con = mysql.createPool({
  host: "localhost",
  user: "User",
  password: "Password",
  database: "errors"
});
// We'll use async/await from ES6
const collectErrors = async() => {
  // Up to here I've only changed syntax to ES6
  let startCollector = new Date();

  // We'll try to iterate through each client. And we use here for..of syntax to allow us using await
  for (let client of clients) {
    // Please, check that client value return correct data. If not, change for..of to your for..each and client variable to clients[a]
    const tbj = await tabletojson.convertUrl("http://example.com" + client + "/page.php?limit=100", {
      stripHtmlFromCells: false
    });
    const result = tgj[0];
    for (rs of result) {
      // I can't check this part, but I hope your example was with correct values.
      let newDate = formatDate(striptag(rs[l]["Date"]), striptag(rs[l]["Time"]));
      let user = getUser(striptag(rs[l]["User"]));
      let link = getUrl(splitError[1]);
      let msg = striptag(rs[l]["Error"]);
      let id = getId(link);
      let splitError = rs[l]["Error"].split("<a href=\"");
      let getType = getType(striptag(splitError[0]));
      // ES6 enhanced object syntax
      datas.push({
        newDate,
        user,
        msg,
        id,
        splitError,
        link,
        getType,
        temp: [newDate, link, type, user, client, id, msg]
      });
    }
  }
  // OK, here we have fulfilled datas array. And we want to save it.
  con.getConnection((err, connection) => {
    // Please, notice, here I've changed your insert query to prepared statement.
    connection.query("INSERT IGNORE INTO entries SET ?", datas, (err, rows) => {
      console.log(err);
      connection.release();
      datas = [];
    });
  });
  // I don't see why do you need timeout here, so I've left it commented.
  // setTimeout(CollectErrors, 10000);
};

// Here your other methods go....

// And to call your async function we'll use IIFE
(async() => {
  await collectErrors();
})();

Вероятно, могут быть ошибки с вставкой mysql, но это не так. Если это произошло, напишите в комментариях, и я помогу вам в этом.

  • 0
    setTimeout требуется, так как мне нужно, чтобы этот скрипт запускался неограниченно каждый установленный интервал.
  • 0
    @arleitiss загляните на npmjs.com/package/node-cron с этим модулем, с которым вы можете справиться с запуском сценария опытным способом
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню