🎻

DATABASE_URL環境変数に付加するserverVersionとは何なのか、省略するとどんな影響があるのか

2024/12/02に公開

Symfony Advent Calendar 2024 の2日目の記事です!🎄✨

Twitter (X) でもちょいちょいSymfonyネタを呟いてます。よろしければ フォロー お願いします🤲

昨日は @ippey_s さんの Symfonyのアトリビュートを使って、依存をいろいろ注入しまくる でした✨

何の話?

Symfonyアプリケーションに doctrine/doctrine-bundle をインストールすると、Flexレシピ参考)によって .env に以下のような設定値の雛形が自動で挿入されます。

# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"

これらの設定値には ?serverVersion=xxx というパラメータが付加されていますが、これが何なのか、省略するとどんな影響があるのか、というお話です。

何なのか

Doctrine DBALは、接続先のDBを抽象化するために Platform というクラス を使用します。

Platform クラスは、DBのベンダー およびバージョン に応じて異なる実装が用意されており、実際に接続するDBに合致するものを使用する必要があります。

そのため、どの Platform を使用するかを決定するために、接続先のDBのバージョン番号の情報が必要となります。

serverVersion は、Doctrine DBALにそれを教えるためのパラメータです。

省略するとどんな影響があるのか

結論としては、

  • 一般的な構成のSymfonyアプリケーションでは、ほとんどの場合設定しなくても実害は特にない
  • ただし、設定しておくことによる弊害も特にないので、できるだけ設定しておくのが無難

という認識でよさそうです。

以下、詳細です。

まず、serverVersion パラメータについてはDoctrine DBALの公式ドキュメントの以下の箇所に解説があります。

https://www.doctrine-project.org/projects/doctrine-dbal/en/4.2/reference/configuration.html#automatic-platform-version-detection

これによると、serverVersion が指定されていない場合、Doctrine DBALは実際にDBに接続し、例えばMySQLの場合なら SELECT VERSION(); をクエリしてバージョン番号を取得する、といった処理を自動で行ってくれます。

serverVersion が指定されていれば、上記の処理は行われず、指定されているバージョン番号を信じて、対応する Platform クラスが使用されます。

設定する/しないによる差はこれだけなので、ほとんどの状況において省略して問題になるケースは稀だと思います。

上記の公式ドキュメントの この部分 には「バージョンの自動検出が行われる場合、通常よりも早期にDB接続が確立される可能性がある」という注意書きのような記述がありますが、それが何か実害に繋がるという言及はなく、経験的にも見聞きしたことはありません。何か懸念すべき事項をご存知の方はコメントいただけると嬉しいです🙏

ただし、以下のスレッドに書かれている内容は考慮に値します。

https://github.com/symfony/symfony/discussions/58491

このstof氏のコメントでは、以下の内容が指摘されています。

  • キャッシュの事前生成(bin/console cache:warmup)を行うためには、使用する Platform クラスが決定されている必要がある
    • 例えば、doctrine/ormのマッピングを確定するにあたり、一部のマッピング設定で Platform に依存する処理が実行される
  • そのため、cache:warmup を実行できるためには、以下のいずれかの条件を満たしている必要がある
    1. serverVersion が指定されている
    2. cache:warmup コマンドのプロセスが DATABASE_URL 環境変数を読み取ることができ、cache:warmup コマンドのプロセスを実行しているサーバーからそのDBに接続する権限がある
  • 2の条件の後半部分が満たされず cache:warmup が実行できないケースがよくある
  • 例えば、Dockerベースの環境で、Dockerfile内で cache:warmup を実行しようとしている場合、この時点でDBサーバーのコンテナがまだ存在していないので、DBに接続できず cache:warmup が実行できない

これはなるほど確かにという内容です。

まとめ

  • DATABASE_URL 環境変数の serverVersion パラメータは、Doctrine DBALにDBのバージョン番号を教えるためのもの
  • 省略された場合は実際にDBにバージョン番号をクエリする処理が自動で実行されるので、省略したからといってDoctrineが動作できなくなるというものではない
  • ただし、Dockerfile内で cache:warmup を使用する構成などでは「DBにバージョン番号をクエリする処理」が実行できないせいで cache:warmup が失敗するといった問題が起こり得るなど、影響はゼロではない
  • とりあえず設定しておくのが無難

以上です。

Symfony Advent Calendar 2024、明日は空きです🥺どなたかぜひご参加ください!

GitHubで編集を提案

Discussion