データベースのACID特性という幻想:現実のWebシステムが選ぶBASE思想と結果整合性

Tech & Logic
スポンサーリンク

「フレームワークのトランザクションアノテーションをつけたから、整合性は完璧です😁」

SpringやRailsの呪文を1行コードの上に貼り付け、ドヤ顔でプルリクエストを出してくる若手を見るたび、胃の奥がシクシクと痛み出す。彼らは信じ切っているのだ。リレーショナルデータベース(RDB)が誇らしげに掲げる「ACID特性」という名の魔法の盾を。

断言する。現実の大規模Webシステムにおいて、教科書通りのACID特性など幻想であり、ただの甘えだ。

フレームワークが隠蔽してくれた薄皮一枚の下で、RDBMSがどれほど血反吐を吐きながらディスクを軋ませ、ロックを奪い合っているか。そして、その欺瞞がノードを跨いだ瞬間にいかに無残に崩壊するか。

今回は、ACIDというお題目に縋り付く愚民たちを叩き起こし、かつてソーシャルゲーム黎明期のエンジニアたちが何を代償にトラフィックをさばいたのか、そして現代の分散アーキテクチャがなぜ血みどろの妥協の果てに「BASE思想(結果整合性)」を選ばざるを得なかったのか、その泥臭い現実をぶち撒ける。

そもそもACIDとは何か:教科書が教える「美しすぎるおとぎ話」

まずは、基本情報技術者試験の教科書に載っているような、耳触りの良いおとぎ話をおさらいしておこう。

  • Atomicity(原子性):処理が「全成功」か「全失敗」のどちらかしかない。中途半端な状態は存在しない。
  • Consistency(一貫性):あらかじめ定義されたルール(制約や外部キーなど)を絶対に破らない。
  • Isolation(独立性 / 隔離性):複数のトランザクションが同時に動いても、順番に1件ずつ処理したのと同じ結果になる。
  • Durability(永続性):コミットが完了したデータは、直後に電源プラグを引っこ抜かれようが絶対に消えない。

美しい。実にお行儀が良い。まるで「この世のすべての処理が、寸分の狂いもなく完全に保護される」かのような錯覚を覚える。

だが、エンジニアを名乗るなら、この4文字の背後でハードウェアとOSが強いられている物理的な代償を直視しろ。

ACIDの裏側でDBが何をしているか理解しろ:ディスクとロックの血みどろの現場

フレームワークの提供するORM(オブジェクト関係マッピング)に甘やかされ、「データを保存する関数を呼んだだけ」と思っている連中は、DB内部で起きている暴力的な処理を知らない。

たとえば、「Durability(永続性)」を保証するために何が起きているか。
メモリ上のキャッシュに書き込んだだけでは永続化されない。DBはトランザクションを確定させるたび、ディスク(ストレージ)のWAL(Write-Ahead Logging)領域へコミットログを物理的に叩き込み、OSに対して容赦なくfsync(物理ディスクへの強制フラッシュ)を発行する。

いくらNVMe SSDが高速化しようが、物理ストレージへの同期書き込みはメモリ操作に比べて圧倒的に遅い。1秒間にさばけるトランザクション数には、物理工学上の絶対的な限界壁が存在するのだ。

さらに凶悪なのが「Isolation(独立性)」だ。
複数のトランザクションが同時に同じ行を読み書きして矛盾が起きないようにするため、DBは内部で狂ったように「排他ロック(ロック待ち)」をかける。

行ロック、テーブルロック、ギャップロック、インデックスロック。
誰かがデータを更新している間、後ろに並んだ何百ものリクエストは全員その場に立ち往生(ブロック)させられる。
運悪く順番が交差すれば「デッドロック」が発生し、エンジンによってどちらかの処理が無慈悲に強制射殺(アボート)される。

MVCC(多版同時実行制御)で読み込みと書き込みの衝突を緩和したところで、限界はある。フレームワークの裏側で、DBはロックの奪い合いとディスクの悲鳴という、泥沼の力技で無理やり「ACIDの美しさ」を演じているに過ぎないのだ。

GREEのエンジニア軍団が直面した地獄:MySQLシャーディングという名の「ACID解体ショー」

単一サーバーの限界を身をもって味わい、ACIDの幻想を力技で粉砕して日本のWeb史に名を刻んだのが、2010年代初頭、ソーシャルゲーム全盛期のGREE(グリー)の開発チームだ。

当時、数千万人のユーザーがガラケーの決定ボタンを連打し、「釣り★スタ」や「探検ドリランド」のガチャを引きまくる。押し寄せるトラフィックの波は、当時の最高スペックのサーバーを単一で用意しようが、数分でディスクが火を噴いて即死する規模に達していた。

「1台のMySQLでACIDを守る」という教科書通りの構成は完全に破綻した。そこでGREEのインフラ・DBエンジニアたちが取った狂気の選択が、数千台規模のMySQLを並べるアプリケーション層シャーディング(水平分割)クラスタの構築だった。

ユーザーIDやデータのハッシュ値をもとに、アプリケーション側で「ユーザーAはMySQLサーバー32番、ユーザーBはMySQLサーバー108番」と、泥臭くルーティングを振り分ける。

この瞬間、RDBMSが誇っていた美しい機能はすべて灰燼に帰した。

  • サーバーを跨いだテーブルのJOINは禁止(メモリ上でマージするか、そもそも設計で排除)
  • 外部キー制約(Foreign Key)など論外(負荷が高すぎて即刻削除)
  • 複数ノードを跨ぐトランザクションのACID保証は完全放棄

「整合性を守ってサイトが死ぬくらいなら、ACIDを捨ててでもパケットをさばき切る」。
教科書が推奨する「正しいRDBの作法」をあえてすべてドブに捨て、MySQLを「極限まで高速なKey-Value Store(KVS)」として酷使する。フレームワークのぬるま湯に浸かった開発者が卒倒するようなこの泥臭い力技こそが、当時の爆発的トラフィックを生き延びた現場のリアリズムだった。

分散環境でACIDは死ぬ:「DBが1台」という妄想を捨てろ

GREEの事例が証明した通り、前述した「NTPの魔境」でも触れたように、現代の大規模システムにおいて「DBが世界にたった1台しか存在しない」などという牧歌的な状況はあり得ない。

ノードが2台以上に分かれた瞬間、「CAP定理」という物理の鉄槌が容赦なくプログラマの脳天を叩き割る。

  • Consistency(一貫性)
  • Availability(可用性)
  • Partition Tolerance(分断耐性)

「この3つを同時に満たす分散システムは存在しない」。ネットワークに分断や遅延(P)が確実に発生する現実世界において、システムは「一貫性(C)」を取ってシステム全体を止めるか、「可用性(A)」を取って一時的なデータの不一致を許容するかの二者択一を迫られるのだ。

分散環境で厳密なACID(特に完全なIsolationとAtomicity)を維持しようとすれば、海を越えたネットワークパケットを何往復もさせ、全ノードで2相コミット(2PC)の合意を取り、世界中のノードを数秒間にわたってロックで固め続けなければならない。

そんなことをすればどうなるか。購入ボタンを押した瞬間、画面が10秒間ぐるぐる回り、その間に背後のDBクラスタはロック待ちで即死する。世界規模のWebサービスで厳格なACIDを貫くことは、工学的な自殺行為に等しい。

現実が選んだ「BASE思想」と「結果整合性」という泥臭き妥協

そこで現代のWebアーキテクチャが血を吐きながら選んだのが、ACIDの対極にある「BASE思想」だ。

  • Basically Available(基本的に利用可能):一部のノードが吹き飛んでも、システム全体は落とさず応答を返す。
  • Soft state(柔軟な状態):データの状態は固定されず、ノード間をパケットが伝播する過程で刻一刻と変化してよい(一時的な矛盾を許す)。
  • Eventual consistency(結果整合性):今すぐ全員が一致していなくてもいい。最終的に、いずれ時間が経てば(Eventual)辻褄が合っていればそれでよしとする。

たとえば、SNSの「いいね!」のカウントやタイムラインの投稿。
あなたが「いいね!」を押した瞬間、地球の裏側にいる友人の画面の数字が同時に「+1」にならなくても、誰も死なない。数秒後に裏側の非同期キューやレプリケーションが追いついて、最終的に数字が合っていればビジネスは成立するのだ。

巨大ECの在庫引き当てですらそうだ。厳密なトランザクションで全ノードをロックするのではなく、裏で「仮押さえ」のイベントを非同期メッセージで飛ばし、万が一在庫切れの重複が起きたら「後からお詫びメールを送ってキャンセル(補償トランザクション)で辻褄を合わせる」。

「絶対に矛盾を起こさない(ACID)」という完璧主義を捨て、「矛盾は起きるものとして受け入れ、ビジネスの運用と非同期処理で後から回収する(BASE)」。これこそが、数千万人のトラフィックをさばく現実のWebシステムが辿り着いた生存戦略だ。

「フレームワークがやってくれる」と妄想するならエンジニアを辞めろ

「@Transactionalって書いておけば、フレームワークがよしなにやってくれるんでしょ?」

そんな思考停止の甘えを抱えたまま分散システムやマイクロサービスに足を踏み入れた開発者は、例外なく本番環境の炎上劇の生贄となる。

HTTPリクエストの跨ぎで中途半端に更新されたデータ。非同期キューの遅延によって発生する幽霊のようなファントムリード。二重引き落としのクレーム。それらを前にして「フレームワークの挙動がバグってます」と言い訳するなら、今すぐエンジニアを辞めて別の仕事を探した方がいい。

フレームワークが隠蔽しているのは「コードの記述量」であって、「システムの物理現象」ではない。

あなたの書いた一行が、ディスクのヘッドをどう揺らし、ネットワークの帯域を何ミリ秒奪い、どのスコープでロックを握り潰しているのか。その冷徹な裏側のコストを骨の髄まで理解した上で、「ここはACIDで守るべき勘定系か、それともBASEで逃がすべき配信系か」を冷徹に切り分ける。

その血の通った設計眼を持たない者に、現代のWebインフラの土俵に上がる資格はないのだ。

タイトルとURLをコピーしました