Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

MongoDB 도큐먼트의 BSON 크기 확인하기

간단한 개인 프로젝트를 하면서 MongoDB를 사용했는데 데이터를 조회하던 중 다음과 같은 connection closed due to parseError 오류가 발생한다.

Thu May 16 2013 19:53:18 GMT+0900 (KST) - error: Error: connection closed due to parseError
  at [object Object].Server.connect (/example/node_modules/mongodb/lib/mongodb/connection/server.js:645:45)
  at [object Object].EventEmitter.emit (events.js:126:20)
  at [object Object]._connect (/example/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:181:15)
  at [object Object].EventEmitter.emit (events.js:99:17)
  at Socket.exports.Connection.createDataHandler (/example/node_modules/mongodb/lib/mongodb/connection/connection.js:357:20)
  at Socket.EventEmitter.emit (events.js:96:17)
  at TCP.onread (net.js:397:14)

오류 메시지만 보면 파싱오류가 발생한 것데 왜 파싱오류가 발생했는지는 추측하기가 쉽지 않다. 이건 소스를 보면 확인할 수 있는데 해당 부분인 connection.js의 소스는 다음과 같다.

if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
  var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
    sizeOfMessage: sizeOfMessage,
    bytesRead: self.bytesRead,
    stubBuffer: self.stubBuffer}};
  if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
  // We got a parse Error fire it off then keep going
  self.emit("parseError", errorObject, self);
  return;
}

메시지가 없거나 최대 BSON 사이즈보다 작은 경우에 오류가 발생한건데 이 경우에는 BSON 사이즈가 최대 크기를 넘어선 경우이다. MongoDB는 BSON(Binary JSON)이라는 데이터형식을 사용하는데 현재 MongoDB의 최대 사이즈는 16MB이다.  과거에는 4MB였는데 1.7.4버전부터인가 16MB로 올라갔고 차후에는 32MB로 올릴 예정인 것으로 알고 있다. 이 값은 참고로 수정할 수 없는 값이므로 MongoDB의 제약사항 중 하나고 MongoDB에서 하나의 도규먼트(RDB라면 하나의 Row)의 최대 크기가 16MB라는 의미이다. 임시적인 프로젝트라서 귀차니즘에 하나의 컬렉션에 데이터를 임베딩해서 넣으면서 16MB가 넘을 일은 없을꺼라고 생각했지만 아마도 넘은듯 하다.(사실 정말 16MB가 넘은지 좀 의심스럽기는 하지만 데이터가 많아서 정확히 확인하지는 못했다.)


BSON 사이즈 확인
MongoDB 쉘에서는 BSON의 크기를 확인할 수 있는 Object.bsonsize()라는 함수를 제공하고 있고 있다.

> Object.bsonsize({})
5
> Object.bsonsize({name:'outsider', url:'http://blog.outsider.ne.kr'})
60

bsonsize()에 객체를 넘겨보면 BSON의 크기를 계산해 볼 수 있다. 위와 같이 객체를 직접 넣는대신 query를 넣어서 확인할 수도 있다.

> Object.bsonsize(db.test.findOne())
988923

위와 같이 findOne() 쿼리를 사용해서 디비에 담긴 특정 도큐먼트의 크기를 확인해 볼 수 있는데 여기서 주의할 점은 findOne()만 되고 find()로는 제대로 확인이 되지 않는다. 여기서 나오는 크기는 바이트크기이므로 988923은 988KB정도가 되는 것이다. BSON 사이즈제한이 의심되는 도큐먼트가 있다면 이 함수를 사용해서 확인해 볼 수 있다.
2013/05/16 23:54 2013/05/16 23:54