원인

MongoDB의 shard key size 제한이 512 바이트인데, insert 하려는 document에서 shard key에 해당하는 부분이 512 바이트를 넘어서기 때문에 발생하는 에러



해결

사이즈 기준이 각 키/값별 데이터 사이즈의 합계인지, 아니면 JSON 문자열의 길이인지 뭔지 몰라서 헤맸는데,

BSON size가 기준이었다.


MongoDB 소스코드에서 shard key size를 체크하는 함수의 매개변수 부분을 보면 BSONObj가 넘어가는 걸 확인할 수 있다.

https://github.com/mongodb/mongo/blob/v3.0/src/mongo/s/shard_key_pattern.cpp#L59

(내가 운용하는 MongoDB 버전이 3.0이라 3.0 버전 소스코드 기준임)



PHP에서 BSON size를 어떻게 구할 수 있을까 찾아보다가,

php-mongo driver의 함수 중 bson_encode() 가 PHP의 변수를 받아 BSON으로 변환해주는 구현체라는 걸 발견했고,

https://github.com/mongodb/mongo-php-driver-legacy/blob/v1.6/bson.c#L1412



bson_encode() 함수와 strlen() 함수를 이용해서 MongoDB shell 명령어인 Object.bsonsize() 와 동일한 결과를 얻을 수 있다는 사실을 알아냈다.

아래와 같은 방식으로 shard key의 size를 미리 체크해서 insert 하기 전에 사고를 방지할 수 있다.



bson_encode() 함수는 deprecated된 php-mongo driver(legacy)에 포함된 함수임.

현역인 php-mongodb driver를 이용한다면 bson_encode() 대신, MongoDB\BSON\fromPHP() 함수를 이용하면 될 듯.


BSON spec을 보니, 맨 앞의 4바이트(int32)가 document의 길이를 나타내므로 bin2hex, hexdec 등을 이용하는 방법을 먼저 해봤는데, 그냥 strlen이 성능상 빠르고 편함.




참고

MongoDB shard key size 제한: https://docs.mongodb.com/manual/reference/limits/#Shard-Key-Size

php-mongo drvier(legacy): http://php.net/mongo

bson_encode(): http://php.net/manual/en/function.bson-encode.php

MongoDB\BSON\fromPHP(): http://php.net/manual/en/function.mongodb.bson-fromphp.php

BSON spec: http://bsonspec.org/spec.html





.






저작자 표시
신고
Posted by bloodguy

댓글을 달아 주세요



티스토리 툴바