SQLite エディション: デフォルト設定を近代化する提案

SQLite エディション: デフォルト設定を近代化する提案

SQLite は、別プロセスではなくライブラリとして提供されることから、ローカルデータ保存の業界標準と広く認識されています。しかし、レガシーなデフォルト設定と現代的なデータベース期待との間には大きなギャップがあります。このギャップを後方互換性を壊さずに埋めるために、"エディション" と呼ばれる単一の pragma を導入し、最新のデフォルト群を有効化する提案があります。

SQLite エディションの必要性

SQLite のように至る所で使われているプロジェクトのデフォルト設定を変更することは、何百万もの既存インストールを壊さないようにするために従来は避けられてきました。提案された解決策は PRAGMA edition = 2026; のような "スーパープラグマ" で、これが一連の最新設定へのエイリアスとして機能します。このアプローチは Rust のエディションにヒントを得ており、エンジンが時間とともにデフォルトを進化させられるようにします(例: 将来の PRAGMA edition = 2034 が WAL2 などの新技術を導入できる)が、レガシーデータベースはそのまま残ります。

更新が必要な重要なデフォルト

現代のアプリケーション開発において問題となっているコア SQLite デフォルトがいくつか特定されています。これらはデータ不整合、バグ、パフォーマンスボトルネックの原因となります。

1. 外部キーの強制

デフォルトでは SQLite は外部キー制約を無視します。これにより、ぶら下がり参照やデータ不整合が発生します。SQLite は ROWID の値を再利用する可能性があるため、削除されたレコードの ID が新しいレコードに割り当てられ、ぶら下がり参照が誤ったデータを指すことがあります(エラーにならない)。

解決策: PRAGMA foreign_keys = ON; で外部キーを有効化します。

2. 型安全性と STRICT テーブル

SQLite は従来 "柔軟な型付け"(affinity)を採用しており、宣言された型に関係なく任意の型の値を列に格納できます。たとえば、INTEGER 列に数値に変換できない文字列を格納できてしまいます。

解決策: STRICT テーブルを使用してデータ型を強制します。カスタム型名(現在は主にドキュメント用途)の有用性を保つため、提案では SQL‑99 標準の CREATE DOMAIN 文をサポートし、カスタム型エイリアスとそれに付随する制約を定義できるようにします。

3. 同時書き込みの取り扱い

デフォルトでは、同時書き込みが発生すると即座に SQLITE_BUSY エラーが返されます。開発者が手動でリトライループを実装していない場合、アプリケーションがクラッシュすることが頻繁にあります。

解決策: busy_timeout を設定し、ロックが解除されるまで待機させてからエラーを返すようにします。 推奨設定: PRAGMA busy_timeout = 5000; (5 秒)。

4. 書き込み性能

デフォルトの SQLite パフォーマンスは、Write‑Ahead Log(WAL)が無効になっているため、サーバー向けのワークロードにはしばしば不十分です。

解決策: WAL モードを有効化し、同期設定を調整して書き込み速度を大幅に向上させます。 推奨設定:

  • PRAGMA journal_mode = WAL;
  • PRAGMA synchronous = NORMAL;

コミュニティの見解と反論

この提案は、SQLite の設計哲学や実装上の実務性について開発者間で大きな議論を呼び起こしました。

エディションに反対する議論

  • 設計意図: SQLite の緩やかな型付けやシンプルなロックは、組み込み環境向けに意図的に設計されたものだと主張する声があります。厳格な ACID 保証や高度な同時実行性が必要なユーザーは、PostgreSQL など別の RDBMS を使うべきだという意見です。
  • C レベルの実装: SQLITE_BUSY のようなデフォルトを変更すると、C プログラマはより厳格なエラーハンドリングとリトライ処理を実装しなければならず、望ましくないと指摘する批判があります。
  • ツールの断片化: エディション情報がデータベースファイルに保存される場合、古いバージョンの sqlite3 CLI ツールが新しいエディションで作成されたデータベースを読めなくなる懸念があります。
  • WAL の制限: WAL モードは別ファイル形式であり、一部プラットフォームでサポートされていない上、サイレントな破損リスクが高まると指摘する声もあります。

エディションに賛成する議論

  • 開発者体験: 現在のデフォルトは、プロフェッショナルな設定に必要なプラグマを知らない開発者にとって "罠" になると主張する人がいます。
  • 代替案: 新しい pragma を作る代わりに、ラッパーライブラリが健全なデフォルトを提供し続けるべきだという意見もありますが、標準化されたクロスランタイムな参照方法があれば、より堅牢になると考えられています。
  • 実装戦略: 組み込みシステムでの肥大化を防ぐため、PRAGMA edition はデータベースファイルに永続的に保存されるのではなく、個々のコマンドに展開されるライブラリレベルのショートカットであるべきだという提案があります。

提案された "2026 エディション" のデフォルト設定の概要

実装された場合、PRAGMA edition = 2026; コマンドは以下の設定と同等になります。

設定 提案デフォルト 効果
foreign_keys ON 参照整合性を強制
busy_timeout 5000 SQLITE_BUSY を返す前に 5 秒待機
journal_mode WAL 書き込み性能と同時実行性を向上
synchronous NORMAL ディスク同期回数を減らしつつ破損リスクは低減
テーブルモード STRICT すべてのテーブルで宣言型データ型を強制

SUMMARY: Rust のエディション方式に倣った "エディション" 機構を SQLite に導入し、後方互換性を損なうことなく、最新で安全かつ高性能なデフォルト設定のセットを有効化する提案です。

TITLE: SQLite エディション: デフォルト設定を近代化する提案

Sources