home
Real MySQL 8.0

쿼리 캐시

4장. MySQL에서 쿼리 캐시가 사라진 이유에 대해 요약

쿼리 캐시는 SQL의 실행 결과를 메모리에 저장해두었다가, 같은 쿼리가 다시 들어오면 테이블을 읽지 않고 캐시된 결과를 바로 돌려주는 기능이다. 한때 웹 애플리케이션의 응답 속도를 끌어올리는 도구로 자주 쓰였지만, MySQL 8.0에서는 완전히 제거되었다.

동작 방식

캐시 키는 SQL 문장 자체였다. 클라이언트가 보낸 쿼리 문자열이 캐시에 있으면 그 결과를 그대로 반환했고, 없으면 쿼리를 실행한 뒤 결과를 캐시에 저장했다. 키가 SQL 문장 자체이기 때문에 공백이나 대소문자만 달라져도 다른 캐시 항목으로 취급됐다.

핵심 한계는 무효화(invalidation) 정책이다. 어떤 테이블에 INSERT/UPDATE/DELETE가 한 번이라도 발생하면, 그 테이블을 참조하는 모든 캐시 항목을 일괄로 삭제해야 했다. 데이터의 일관성을 보장하려면 다른 선택지가 없었다.

왜 제거됐나

문제는 무효화가 너무 자주, 너무 무겁게 일어났다는 점이다.

  • 쓰기가 조금이라도 섞인 워크로드에서는 캐시가 거의 항상 비워졌다. 캐시 적중률이 기대만큼 높지 않았다.
  • 캐시를 읽거나 무효화할 때 내부적으로 mutex 락을 잡아야 했고, 이게 동시 처리의 병목이 되었다. 결과적으로 쿼리 캐시를 켜면 오히려 성능이 떨어지는 경우가 많아졌다.
  • 멀티코어 환경이 보편화되면서 이 락 경합 비용은 더욱 커졌다.

MySQL은 5.7에서 쿼리 캐시를 기본 비활성화했고, 8.0부터는 관련 시스템 변수(query_cache_size, query_cache_type 등)까지 모두 제거했다.

대안

쿼리 결과 캐싱이 필요하다면 MySQL 외부에서 처리하는 것이 표준이 되었다.

  • 애플리케이션 레벨 캐시 — Redis, Memcached
  • 프록시 레이어 캐시 — ProxySQL의 query cache
  • HTTP/CDN 레이어의 응답 캐시

이쪽은 무효화 정책을 애플리케이션 도메인 지식에 맞게 세밀하게 다룰 수 있어, 내장 캐시처럼 일률적인 전체 무효화를 피할 수 있다.

댓글

아직 댓글이 없습니다.