如何使用节点流将大数据插入mysql?

时间:2019-01-30 19:44:50

标签: mysql node.js stream

我正在尝试使用节点流将一千万条记录插入到mysql中。有没有办法用节点流来做到这一点?我找不到任何关于此问题的非常有用或“友好”的答案或文档。到目前为止,我已经可以插入45,000条记录,但是尝试使用大于此值的记录集会遇到一些错误。

此外,下面的代码在这里应该执行的回调是什么?我不确定我从哪里来的代码,实际上也没有传递回电话,所以,也许就是问题所在! :D有什么想法吗?回调实际上是什么?也许回调应该一次占用一个块并一次传递一个块?我该如何进行修改以使其始终如一地工作?我只是认为下面的这段代码实际上根本没有将数据分成多个块。如何将其拆分为可管理的块?

根据记录的数量,我尝试使用此方法会得到不同的错误。我遇到的错误是:

对于50K-80K有时会出现此错误:

Error: connect ETIMEDOUT
    at Connection._handleConnectTimeout  

对于10万条或以上记录,我得到此错误:

 Error: ER_NET_PACKET_TOO_LARGE: Got a packet bigger than 'max_allowed_packet' bytes
        at Query.Sequence._packetToError

大约55K记录的错误:

Error: write EPIPE
    at WriteWrap.afterWrite [as oncomplete] (net.js:788:14)

根据我要插入的记录数量,会出现3种不同的错误是很疯狂的事情。

下面是代码(对于45000条记录,它工作正常,但对于更大的记录,则不是):

var db = require('./index.js');
var faker = require('faker');
var stream = require('stream');

var songs = [];

var size = 10000000; 

var songList = function(){
  for (var i = 0; i < size; i++) {
      var song = [i, faker.random.words(1,2), faker.name.findName(), faker.internet.url(1,50), faker.random.words(1,2), faker.random.words(1,20)];
      songs.push(song);  
    }
  console.log('songs', songs);  
  return songs;
}

var songSql = "INSERT INTO songs (song_id, song_name, artist, song_url, song_album, song_playlist) VALUES ?";

var songValues = songList();

var songSeed = function() {
  console.log('x: ', x);
  var query = db.connection.query(songSql, [songValues]).stream({highWaterMark: 5});
  var testStream = new stream.Transform({highWaterMark: 5, objectMode: true});
  testStream._write = function(chunk,encoding,callback) {
    setTimeout(function() {
      console.log('my chunk: ', chunk);
      callback();
    },1000);
  }
  // Pipe the query stream into the testStream
  query.pipe(testStream)

  // Monitor data events on the side to see when we pause
  query.on("result",function(d,i) {
  console.log("Data Sent")
  })
}

songSeed();

1 个答案:

答案 0 :(得分:1)

在MySQL服务器上,将max_allowed_packet增加到1G。这没有真正的缺点。