[PHP + MySQL] 대용량 데이터 select시 메모리 에러 발생

욱이로그·2022년 10월 18일
0

작은 스타트업에서 인턴 나부랭이로 잘 지내고 있는데 최근에 실제 운영중인 서비스의 DB Server가 터져서 문제가 많았다.. 터진 이유를 보니까 레거시 코드에서 사용자 입출입 Log, API 호출 Log 등 + 불필요한 row를 무작정 쌓아놔서 터졌다..!

이 부분에서 Linux Crontab을 사용해서 정기적으로 데이터를 삭제 또는 가공해서 불필요한 row 수를 줄여줘서 DB에 부하를 줄여주는 작업을 맡게 되었다. 나는 사용자 입출입 Log에 대한 테이블 처리를 맡았다!

PROD-SLAVE DB를 열어보니 약 1500만 - 2000만개의 log가 쌓여있었다.

어떻게 효율적으로 코드를 짜야하지 많은 고민을 해봤는데..
머리속에는 2가지 방법 밖에 떠오르지 않았다.

1. Query로 모든 처리를 함 (SELECT, SUM/MIN/MAX, INSERT, DELETE 등)
2. API 자체에서 SUM, GROUP BY 등을 진행해서 shop, member 별로 처리

사실 둘다 좋은 방법은 아니라고 생각한다.

1번 같은 경우에는 무작정 쿼리문으로 때려 넣기 때문에 그렇게 썩 좋은 방법은 아닌 것 같았다. 다만 저렇게 생각하게 된 계기는 약 1500만 개 데이터 정도는 속도가 느려지거나 서버에 큰 영향을 주지 않는 이상 자주 하는 작업이 아니다 보니 괜찮지 않을까? 싶어서 생각해봤다.

2번 같은 경우에는 팀장님이 CodeIgniter에서 동기 처리가 가능하게 Custom 해놓으신 라이브러리가 있었는데 그걸 가져와서 진행을 하면 1번보다 더 효율적으로 진행할 수 있을 것이라고 생각했다.

먼저 그냥 1번으로 생각없이 진행했다. 데이터 수가 1억개 처럼 엄청 많지는 않지만 적은 데이터도 아니기 때문에 인덱싱을 걸어줘서 쿼리문 작성해봤다. 이후 테스트를 해보니.....

Allowed memory size of -- bytes exhausted (tried to allocate -- bytes) in php [duplicate]

한 5분 ~ 10분정도 지나고 나니 저런 에러가 발생했다.
메모리 문제였던 것 같다!

구글링을 통해 자료를 찾아보니 php.ini 파일에 memory_limit 부분을 늘려줄 수 있었다!

ini_set('memory_limit', '1024M');

로 진행했더니 API가 약 2분 30초 정도 소요되었고 데이터는 정상적으로 처리 되어서 DB에 Setting이 되어있었다.

다행히.. 팀장님께서 OK 해주셨다..!
자주하는 작업 아니고 (3개월에 1번?) 메모리도 많이 늘려준 부분은 아닌 것 같고 시간도 적당한 거 같아서 사용해도 괜찮을 것 같다고 얘기해주셨다. (휴우)

이제 다음주에 있을 새벽작업에 CRONTAB에 해당 API를 적용시켜서 테스트 해보고 배포 다시 하려고 한다.
새벽작업 전에 2번 방법도 한번 구현을 해서 소요시간 비교를 해보려고 한다!

사실 별거 아니지만... 나름 뿌듯🎉


https://stackoverflow.com/questions/415801/allowed-memory-size-of-33554432-bytes-exhausted-tried-to-allocate-43148176-byte

https://jojoldu.tistory.com/m/243

profile
뭐든 해보고싶은 개발자

0개의 댓글