3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者向け】SQLiteと他のデータベースの違い ― FastAPIで学ぶ `check_same_thread` の謎

3
Posted at

はじめに

FastAPIとSQLAlchemyでデータベース接続を設定しているとき、こんなコードを見たことはありませんか?

engine = create_engine(
    settings.DATABASE_URL,
    connect_args={"check_same_thread": False}  # SQLite only
)

この check_same_thread=False って何?なぜSQLiteだけ必要なの?

この記事では、前提知識から丁寧に解説していきます。

この記事で学べること

  • スレッドとは何か
  • Webサーバーがどのように動くか
  • SQLiteと他のデータベースの違い
  • なぜ check_same_thread=False が必要なのか

1. まず「スレッド」を理解しよう

スレッドとは?

スレッド = プログラム内で同時に動く作業単位です。

レストランのキッチンでたとえてみましょう。

【シングルスレッド(料理人1人)】

注文A → 調理 → 完成 → 注文B → 調理 → 完成
(1つずつ順番に処理)


【マルチスレッド(料理人3人)】

注文A → 料理人1が調理 ─┐
注文B → 料理人2が調理 ─┼─ 同時進行!
注文C → 料理人3が調理 ─┘

マルチスレッドだと複数の処理を同時にできるので効率的です。

2. Webサーバー(FastAPI)の動き

ユーザーがWebサイトにアクセスすると「リクエスト」が発生します。

ユーザーA → リクエスト「ユーザー一覧見せて」
ユーザーB → リクエスト「商品を購入したい」
ユーザーC → リクエスト「ログインしたい」

FastAPIは複数のリクエストを同時に処理するため、内部でスレッドを使います。

リクエストA → スレッド1 が担当
リクエストB → スレッド2 が担当
リクエストC → スレッド3 が担当

FastAPIは非同期処理も使いますが、同期的なDB操作ではスレッドプールが使われることがあります。

3. データベース接続とは?

プログラムがデータベースを使うには、まず「接続」を確立します。

プログラム ←――― 接続 ―――→ データベース
            (パイプのようなもの)

この接続を通じて「データをください」「データを保存して」とやり取りします。

4. SQLiteと他のDBの決定的な違い

SQLiteの特徴

SQLiteはファイル1つで動く軽量データベースです。

項目 SQLite PostgreSQL / MySQL
構成 ファイル1つ(database.db サーバーとして常駐
セットアップ 不要 サーバー構築が必要
複数アクセス 制限あり 想定済み
用途 開発・小規模 本番・大規模

SQLiteの安全機構

SQLiteは軽量な反面、スレッドに関する安全機構があります。

「この接続はスレッドAで作ったから、スレッドAだけが使ってね」

これにより、マルチスレッドでの不整合やデータ破損を防いでいます。

5. 問題が起きる状況

FastAPIとSQLiteを組み合わせると、以下のような問題が発生します。

① サーバー起動時にDB接続を作成(スレッドAで作成)
          ↓
② ユーザーからリクエストが来る
          ↓
③ FastAPIがスレッドBでそのリクエストを処理
          ↓
④ スレッドBが①の接続を使おうとする
          ↓
⑤ SQLite「それスレッドAで作った接続でしょ?ダメ!」
          ↓
   💥 エラー発生!

実際のエラーメッセージ:

sqlite3.ProgrammingError: SQLite objects created in a thread 
can only be used in that same thread.

6. 解決策:check_same_thread=False

engine = create_engine(
    settings.DATABASE_URL,
    connect_args={"check_same_thread": False}
)

この設定をすると、SQLiteに「スレッドのチェックをしないで」と伝えます。

【デフォルト(check_same_thread=True)】

スレッドA で接続作成
    ├→ スレッドA からアクセス → ✅ OK
    └→ スレッドB からアクセス → ❌ エラー


【check_same_thread=False】

スレッドA で接続作成
    ├→ スレッドA からアクセス → ✅ OK
    └→ スレッドB からアクセス → ✅ OK(チェック無効化)

7. 他のデータベースでは不要

PostgreSQLやMySQLは、最初からマルチスレッドを想定して設計されています。

そのため、check_same_thread のような設定は存在しません。

# PostgreSQLの場合
engine = create_engine("postgresql://user:pass@localhost/dbname")
# → check_same_threadは不要(そもそも存在しない)

8. 本番環境での対応

開発環境ではSQLite、本番環境ではPostgreSQLを使うことが多いです。

その場合は、条件分岐で設定を切り替えましょう。

# 環境に応じて設定を切り替える
if "sqlite" in settings.DATABASE_URL:
    connect_args = {"check_same_thread": False}
else:
    connect_args = {}

engine = create_engine(settings.DATABASE_URL, connect_args=connect_args)

まとめ

観点 SQLite PostgreSQL / MySQL
スレッド対応 制限あり 対応済み
check_same_thread 必要(Falseに設定) 不要
用途 開発・テスト 本番環境

check_same_thread=False はSQLiteの安全機構を無効化するため、本番環境では適切なデータベース(PostgreSQL等)への移行を推奨します。

参考

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?