Cloudflare는 Hyperdrive에서 MySQL 지원을 정식 출시했다고 발표했다. Hyperdrive는 Workers 사용자를 대상으로 데이터베이스 연결을 풀링하고 회사 네트워크를 통해 재사용하는 서비스다. 베타 버전에서 정식 출시로 전환한 것은 약 20개의 버그를 해결한 이후였으며, 여기에는 데이터가 있을 것으로 예상했음에도 빈 응답을 발생시킨 쿼리 결과 캐싱 관련 드문 문제가 포함됐다.
이 문제는 약 0.001%의 비율로 발생해 추적 로그를 통한 탐지가 어려웠다. Cloudflare는 캐싱을 활성화했을 때만 버그가 나타난다는 사실을 확인했으며, 베타 단계에서 MySQL 서비스를 가장 많이 사용한 고객이 이를 신고한 이후 문제를 발견했다.
Hyperdrive는 어떻게 작동하는가?
Hyperdrive는 Cloudflare 네트워크에 SQL 연결을 활성 상태로 유지하고 열어 둔 뒤, 요청마다 새 연결을 생성하는 대신 Workers 요청 간에 이를 공유한다. 또한 일반적인 쿼리 결과를 로컬 CDN 메모리에 저장할 수 있어 지연 시간과 원본 데이터베이스에 가해지는 부담을 줄인다.
서비스 아키텍처는 Worker 가까이에서 작동하는 Client 노드와 연결 풀을 관리하며 원본 데이터베이스와 가까운 데이터센터에 위치하는 Endpoint 노드로 구성된다. 두 노드는 같은 데이터센터에서 작동할 때 동일한 캐시를 공유할 수 있다.
버그는 MySQL 프로토콜 형식의 차이에서 발생했다
Hyperdrive는 서로 다른 두 측면에서 MySQL을 처리한다. Worker 앞에서는 서버로 작동하고, 원본 데이터베이스 앞에서는 클라이언트로 작동한다. Worker가 협상하는 프로토콜 기능과 Hyperdrive가 데이터베이스에서 사용하는 기능이 다를 수 있기 때문에, 서비스는 최종 클라이언트에 맞도록 결과 메시지의 형식을 다시 구성해야 한다.
조사는 결과 집합을 종료하는 방식에 초점을 맞췄다. Node.js에서 널리 사용되는 mysql2 라이브러리를 포함한 일부 MySQL 라이브러리는 CLIENT_DEPRECATE_EOF 기능을 지원하지 않는다. 이 기능이 없으면 서버는 EOF 패킷을 사용하지만, 최신 프로토콜 동작에서는 결과 집합 끝에서 이를 OK 패킷으로 대체한다.
Client 노드는 때때로 Worker의 기능에 맞게 변환한 후의 바이트를 저장한 반면, Endpoint 노드는 Hyperdrive의 기능을 사용하는 표준 버전을 예상했다. 한 노드가 다른 노드가 저장한 결과를 읽을 때 메시지를 적절하지 않은 형식으로 처리할 수 있었고, 그 결과 조기 EOF, 중단 또는 빈 결과가 발생했다.
실제로 무엇이 바뀌었나?
Cloudflare는 모든 노드가 캐시에 쿼리 결과의 표준 버전을 기록하도록 변경해 문제를 해결했다. 이 버전은 결과를 저장한 노드와 관계없이 항상 Hyperdrive의 기능에 따라 인코딩된다. Cloudflare에 따르면 수정 사항을 배포한 후 빈 행 문제가 사라졌으며 Client 연결 성공률은 99.99%에 도달했다.
회사는 테스트 중 나타난 다른 문제들도 해결했으며, 여기에는 이모지 인코딩 오류가 포함된다. utf8을 사용하면 실제로는 모든 4바이트 Unicode 코드 포인트를 지원하지 않는 utf8mb3을 가리키고 있었다. 서비스는 utf8mb4로 전환했다. 또한 COM_RESET_CONNECTION 명령을 실행한 후 인코딩을 다시 설정했다. 이 명령은 연결을 서버의 기본 설정으로 되돌리며, 해당 설정은 latin1일 수 있기 때문이다.
가용성과 제한 사항
MySQL 지원은 오늘부터 Cloudflare 대시보드 또는 wrangler 도구를 통해 일반적으로 사용할 수 있으며, 새 PlanetScale 데이터베이스에 대한 연결을 포함해 호환되는 MySQL 데이터베이스와 함께 사용할 수 있다. 이번 사례는 중간 계층에서 연결 풀링과 캐싱을 수행하는 일이 SQL의 정확성에만 의존하지 않으며, 각 계층이 예상하는 프로토콜 상태와 형식이 정확히 일치해야 한다는 점을 보여준다.