SQLite3 はなぜ本番環境で使えるようになったのか


前回の記事では、「Minimum Rails」と称して、Rails 8 の推奨する技術スタックを紹介しました。

  • フレームワーク: Ruby on Rails
  • データベース: SQLite3
  • コンテナオーケストレーション: Docker
  • デプロイ: kamal
  • TLS 対応: kamal-proxy
  • インフラ: Linux サーバーが1台あれば何でもOK

この技術スタックを知った時、筆者が最も驚いたのは「本番環境で SQLite3 を使っている」という点です。 モダンな Web アプリケーションなら MySQL か PostgreSQL だ!SQLite3 は使うな!そう言われた時代が確かにあったはずです。

そこで今回のテーマです。

  • なぜ SQLite3 を本番環境で使うことはできなかったのか
  • Rails 8 が現れた今、当時と何が変わったのか

これらについて、詳しく調べてまとめます。4本の記事からなるシリーズものとなります。

そもそも SQLite3 とは?

SQLite3 を一言で表すなら「サーバーレスなリレーショナルデータベース」です。

多くの Web アプリケーションで採用されている MySQL や PostgreSQL とは、根本的に異なる設計思想で作られています。 その大きな特徴は2点あります。

  • データベースのデータ本体が「単一のファイル」
  • データベースのエンジン部分が「アプリケーションプロセスにライブラリとして内包される」

そのシンプルさ、ネットワーク通信やプロセス間通信のオーバーヘッドを削減できる軽量さゆえに、iPhone、Android、IoT 機器、Google Chrome 等のブラウザといった様々な場所で使われています。 「本番で動いている数」が、最も多いリレーショナルデータベースは SQLite3 でしょう。

Web アプリケーションと SQLite3

にもかかわらず、Web アプリケーション開発の分野では、SQLite3 を本番環境で利用することは「禁忌」でした。 これには明確すぎる「根拠」があります。

  1. 同時アクセスに弱い
  2. 水平スケールが困難

つまり、成長する(ユーザーが増える)サービスには不向きだと考えられてきたわけです。

同時アクセスに弱い

SQLite3 のデータ本体たるファイルに書き込みを行おうとすれば、排他ロックを獲得する必要があります。つまり、1つのトランザクションが書き込みを行っている最中、他のトランザクションは読み込みも書き込みもできません。ただひたすら待たされます。

また、ロックの粒度を細かくすることも困難です。ファイルに書き込むならファイル全体の排他ロックを取る必要があります。たった1レコードの挿入がデータベース全体をロックしてしまうでしょう。

Web アプリケーションの場合は、何百、何千、あるいはそれ以上のユーザーが、同時にリクエストを送り、Web サーバーはそれを並列・並行処理します。 SQLite3 へのアクセスがボトルネックになることは明らかです。

水平スケールが困難

データ本体が「ファイル」である以上、複数のサーバーでデータを共有することは困難を極めます。 無理やりファイルを共有しようとすれば、SQLite3 のシンプル・軽量というメリットが損なわれるだけでなく、OSのファイルロック機構に依存する「整合性の保証」も破綻しかねません。

中規模以上の Web アプリケーションでは、Web サーバーを複数台用意して、可用性を高めるのが常識。 単一サーバーに縛られる SQLite3 では厳しい、となるのも当然です。

まとめ

SQLite3 の特徴と、Web アプリケーション開発において「おもちゃ」という立ち位置に甘んじてきた理由を解説しました。

この SQLite3 が、Rails 8 とともに本番環境で使えるようになった背景には

  • SQLite3 のデータ管理の進化
  • sqlite3-ruby のデータアクセス方法の進化
  • Rails の SQLite3 アダプターの進化

これらの技術革新があります。

次回以降、SQLite3 と Ruby on Rails の歩みを辿っていきましょう。

フィードバックを送る

  • • お送りいただいた内容は、筆者が全て目を通し、今後の励みとさせていただきます
  • プライバシー: お名前やメールアドレスの収集は行っておりません
  • 返信: 全てへの返信はお約束できかねますが、必要な場合は本文内に連絡先を添えてください
  • 公開の可能性: 個人を特定できない形で記事内で紹介させていただく場合があります