テック技報最新号へ →
インフラ

Hyperdrive の MySQL 対応で見つかった落とし穴: utf8 は utf8mb3、リセット後の文字コード、ケーパビリティ差

Workers から MySQL へつなぐ Hyperdrive の MySQL 対応が GA になり、ベータ中に直したバグが公開された。自前でコネクションプールやプロキシを作る・使うときにも当てはまる MySQL プロトコルの注意点が 3 つある。

@Cloudflare · 2026-10-16
#infra#cloudflare#hyperdrive#mysql#database

どんなときに使う?

  • Workers × Hyperdrive で MySQL を使う(または移行を考えている)とき
  • ProxySQL などのコネクションプーラーやキャッシュ層を挟んで、絵文字化けや空の結果に悩んでいるとき

落とし穴 1: utf8 は完全な UTF-8 ではない

MySQL の utf8 は utf8mb3 の別名で、1 文字 3 バイトまでしか扱えない。絵文字など 4 バイト文字が壊れる。接続時の文字コードは utf8mb4 を指定する。

落とし穴 2: COM_RESET_CONNECTION で文字コードがサーバー既定に戻る

プールした接続を使い回す前にセッション状態を消す COM_RESET_CONNECTION は、文字コードを「接続時に決めた値」ではなく サーバーの既定値(例: latin1)に戻す。リセットのたびに文字コードを utf8mb4 に設定し直す。

落とし穴 3: クライアントごとにケーパビリティが違う

  • MySQL は接続時に、使う機能(ケーパビリティ)をクライアントとサーバーで決める
  • Node.js の mysql2 は CLIENT_DEPRECATE_EOF に対応していない。この場合、結果セットの区切りが OK パケットではなく EOF パケットになる
  • Hyperdrive は内部の固定ケーパビリティでオリジンと話し、Worker 側のドライバーに合わせて応答を書き換えている
  • バグの原因は「Worker に返した(書き換え後の)バイト列」をキャッシュしていたこと。同じデータセンターでキャッシュを共有するノード同士で形式が食い違い、約 0.001% の確率で空の結果やハングが起きた
  • 修正は、キャッシュには 常にプーラー内部の形式(正規形) で保存し、返すときに変換すること。これで接続の成功率が 99.99% に達した

使い始め方

npx wrangler hyperdrive create HYPERDRIVE_NAME --connection-string="mysql://user:[email protected]:3306/dbname"

料金は Postgres 版と同じ。既存のドライバーや ORM がそのまま使える。

注意点

  • 1〜3 は Hyperdrive 側で修正済み。ただし自前のプーラーやキャッシュ層を作るときは同じ罠を踏みうる
  • テーブル・カラムの文字セットも utf8mb4 になっているかを別途確認する

出典

X の元の投稿を開く