それでも外部キー制約は必要ない / #fk_night でしゃべってきました

2026/2/8

こんにちは、osyoyu です。外部キーNight 2026ではありがとうございました。外部キー制約不要派の先鋒として適当なことを放言していくぞ!! と意気込んでいたところ、まさかの孤軍奮闘でした(!)。しかし最後は引き分けに持ち込めて良かったですね(?)。

[https://connpass.com/event/380098/:event]

何が言いたかったの

外部キー制約は運用上の障壁になるだけでなく、整合性を守る仕組みとしては力不足すぎる。システム全体のことを考えたとき、不変条件はアプリケーションにエンコードせざるを得ないのだから、そちらに寄せるほうが合理的。

でした。

一定の害が存在することについては、会の中でも認められていたように思います。スキーマの変更を阻害するだとか、パーティショニングできなくなるとか、特にMySQLでは性能劣化が大きいとか、そういうやつです。懇親会でも「トレードオフとして受け入れられる」という声が大きかったように記憶しています *。そこで、この記事では外部キー制約の害ではなく、外部キー制約の力不足さと、制約の記述をアプリに寄せたい世界観について議論してみようと思います。

* これも別に同意していません。スキーマを変えられないのってつらくない?

リレーショナルモデル(DDL)はシステムの不変条件を表現するには弱すぎる

「データの整合性は何よりも大事」という論点には完全に同意するものですが、その整合性を表現するツールとしてのリレーショナルモデルはもはや力不足すぎます。「リレーショナルモデル」という言葉が出てくると衒学的な話に発散しがちですので、ここではDDL(CREATE TABLE)で表現できる範囲、としましょう。

実のところ、これ自体は同意いただけるのではないでしょうか。「ユーザーは住所登録を保留し、address = null のまま登録を完了できる」「しかし address = null のユーザーは商品を注文できない」現実にも類例がたくさんありそうですが、 CHECK を使ってもこの "整合性" は守れません。しかしこのタイプの要件はごまんとありそうです。

あるいは、「お金を扱うから整合性をしっかり守りたい」というフレーズにしても、外部システム(たとえばStripe)が関わった途端に話はRDBMSの世界の外に飛び出てしまいます。より悪いことに、保証が極めて弱いことで知られる "インターネット" を通してやりとりすることになります。ここでDDLの制約は明らかに無力です。ユーザーがStripe上で決済を完了した後、コールバックを受け取り損ねたら払ったお金の対価は受け取れません。RDBMSに決済をロールバックする力はないです。整合性を破る "分散" はスケールの果てにあるものではなく、思ったよりずっと身近です(S3に何かを書いただけでもそう)。

我々は賢いので、このようなケースでも "整合性" を保つ術を編み出し、使ってきました。住所登録の例であればトランザクションとロックで守れますし、そうでないStripeのケースでも非同期に検証する方法が用意されています(結果整合性)。これは「アプリケーションや外部システムを含めて一つの大きな系(システム)として捉えて、不変条件(守るべき整合性)をよく設計して守る」という、実務家的な態度です。そして、条件を記述するに足る表現力をもつのは、SQLではなく汎用言語で書かれたアプリケーションです。

また、さらに記述力を高めるべく、プログラミング言語やライブラリの側も進化しています。たとえば、強力な型システムを持っている言語(RustやTypeScript)では、DBでは共通の型 bigint をもつ users.idorders.id に、それぞれ異なる型を与えることで取り違えを防ぐことができます。便利な時代ですね。

「MySQLはKVS」

という言葉を10回ぐらい聞きましたが、これは70%ぐらいその通りだと思っています。70%ぐらいというのは、ストレージとしてのRDBMSは「タプル(行)を保存できて、特定の条件下では高速にクエリできる容れ物」ぐらいの期待でいるのがちょうど良いと本気で思っているからです(「好きなデータベースはDynamoDB」という自己紹介と整合していませんか)。

つまり、私はRDBMSは「整合性を強く保つための強力な機構」だとはあまり思っていないのです。ACIDで言えば、A(原子性)D(持続性)には強く期待していますが、C(一貫性)は別の機構で守るべき、という主張です。

I(独立性)は…… SERIALIZABLE で運用されているMySQL/PostgreSQLは見たことないですね……

ところで同意していない残りの30%は、極めて強力な機構であるトランザクションとロックがスコープに入っていない点です。不変条件の記述をアプリケーションに寄せようとする中でも、この2つはツールとして必要になりがちです。

まとめ・感謝

「外部キーの益が無いこと」を説明しようと思ったのですが、無いものの証明は難しいですね。単に運用がつらいから制約を弱めようという話をしているのではなくて、システム全体のことを考えたらアプリに不変条件を記述することになるし、そのとき外部キー制約の出番はないよね、という風にご理解いただけたら幸いです。

害が発生しない条件下では外部キー制約を導入して悪いことにはならないでしょう。が、激しく変化するアプリケーションであればあるほど、その条件は想像以上に狭いものとも同時に思います。

この世界観はたくさんの個別事例を通してうっすらとは育んできていたのですが、外部キーNightと懇親会での議論を通し、改めて向き合うことができました。開催してくれた id:moznion、そして会場提供のFindyさん、ありがとうございました!