10 ポイント 投稿者 GN⁺ 2024-01-16 | 1件のコメント | WhatsAppで共有

Wal2 モードの有効化/無効化

  • SQLite の「Wal2」モードは、「wal(Write-Ahead Logging)」モードと非常によく似ています。
  • データベースを wal2 モードに変更するには、PRAGMA journal_mode = wal2; コマンドを使用します。
  • 「wal」モードから直接「wal2」モードに変更することはできず、まずロールバックモードに変更する必要があります。
  • wal モードのデータベースを wal2 モードに変更するには、PRAGMA journal_mode = delete; の後に PRAGMA journal_mode = wal2; コマンドを使用します。
  • wal2 モードのデータベースは、そのブランチでコンパイルされた SQLite バージョンでのみアクセス可能です。
  • 他のバージョンの SQLite を使用しようとすると、SQLITE_NOTADB エラーが発生します。
  • wal2 モードのデータベースをロールバックモードに変更して、すべてのバージョンの SQLite からアクセス可能にするには、PRAGMA journal_mode = delete; コマンドを使用します。

Wal2 モードの利点

  • 従来の wal モードでは、ライターがデータベースにデータを書き込む際、データベースファイルを直接変更せず、「-wal」ファイルに新しいデータを追加します。
  • 読み取り処理は、元のデータベースファイルと「-wal」ファイルの両方からデータを読み取ります。
  • ある時点で、「-wal」ファイルからデータベースファイルへデータがコピーされ、これを「チェックポイント」と呼びます。
  • チェックポイントは、PRAGMA wal_checkpoint または sqlite3_wal_checkpoint_v2() によって明示的に実行されるか、PRAGMA wal_autocheckpoint を設定して自動的に実行されます(デフォルト設定)。
  • チェックポインタはライターをブロックせず、ライターもチェックポインタをブロックしません。
  • しかし、チェックポイント中にライターがデータベースへ書き込むと、新しいデータが wal ファイルの末尾に追加されるため、wal ファイルが継続的に大きくなる可能性があります。
  • wal2 モードでは、チェックポインタが妨げられずに完了する機会がなくても、wal ファイルが無制限に肥大化する問題はありません。
  • wal2 モードでは、1 つではなく 2 つの wal ファイル(「-wal」および「-wal2」)を使用します。
  • データが書き込まれると、ライターは最初の wal ファイルへの新しいデータの追加を開始します。
  • 最初の wal ファイルが十分に大きくなると、ライターは 2 番目の wal ファイルにデータを追加し始めます。
  • その後、最初の wal ファイルはチェックポイント可能になり、2 番目の wal ファイルが十分に大きくなって最初のファイルのチェックポイントが完了すると、再び最初のファイルへ切り替わります。

アプリケーションプログラミング

  • ユーザーの観点から見ると、wal モードと wal2 モードの主な違いはチェックポイントに関係しています。
  • wal モードではいつでもチェックポイントを試みることができますが、wal2 モードではライターが「もう一方の」wal ファイルへ切り替えた後でなければチェックポイントできません。
  • wal モードでは、トランザクションがコミットされた後、wal ファイルの総ページ数を引数として wal-hook(コールバック)が呼び出されます。
  • wal2 モードでは、wal-hook は 2 つの wal ファイルにある未チェックポイントページの合計数を引数として、または「もう一方の」wal ファイルが空かすでにチェックポイント済みであれば 0 を引数として呼び出されます。
  • クライアントには、wal2 モードのデータベースに対しても wal モードと同じチェックポイント戦略を使用することが推奨されます。
  • wal-hook はトランザクションがディスクにコミットされ、データベースロックが解放された後に呼び出されますが、sqlite3_step() 呼び出しの内部で発生します。
  • BEGIN CONCURRENT システムでは、wal-hook 内でチェックポイントを実行する代わりに、アプリケーションミューテックスが解放された後でこの処理を遅延させるスレッドを使用できます。

GN⁺の意見

  • SQLite の wal2 モードは、データベースの並行性と効率を向上させる新しいジャーナリング方式を提供します。
  • wal ファイルの無制限な肥大化の問題を解決し、システムの安定性と性能を改善することが重要です。
  • 開発者は wal2 モードの導入に伴い、データベースのチェックポイント戦略を見直し、より良い並行性のために適切なチェックポイントロジックを実装する必要があります。

1件のコメント

 
GN⁺ 2024-01-16
Hacker Newsのコメント
  • WAL2モードでは、1つではなく2つのWALファイルを使用する。ファイル名は<データベース>-wal<データベース>-wal2になる。データがデータベースに書き込まれる際、書き込み処理は最初のWALファイルに新しいデータを追記することから始まる。最初のWALファイルが十分に大きくなると、書き込み処理は2つ目のWALファイルにデータを追記するよう切り替わる。この時点で最初のWALファイルはチェックポイント可能になり、その後で上書きできる。2つ目のWALファイルが十分に大きくなり、かつ最初のファイルのチェックポイントが完了すると、再び最初のWALファイルへ切り替わる。このプロセスが繰り返される。

    • この方式は非常に理にかなっていて、なぜ最初からWALモードがこのように実装されなかったのか理解できない。おそらく時期尚早な最適化と見なされたのだろう。
    • このモードが一般提供されることを期待している。
  • Bedrock

    • Bedrockのほうがより興味深いブランチだ。
    • WAL2 + CONCURRENT機能を含んでいる。
    • Expensifyが単一ノードで4M QPSまでスケールさせるために使っているブランチだ(6年前)。
  • WAL2モードに似た技術であるleft-right primitiveへのリンクあり。

    • この技術はリンク先の実装より古いが、独立に再発見されたもので、特にNoriaという別の高性能SQLデータベースを支えるために書かれた。
  • WAL2モードでは、1つではなく2つのWALファイルを使用する。ファイル名は<データベース>-wal<データベース>-wal2になる。

    • wal2に切り替わったのだからwalファイルは残り物だと思って、walファイルを削除してしまう人がどれだけいるのか気になる。
  • Microsoft SQL Serverは似たアーキテクチャを使っているが、別個のログファイルではなく、物理的な(ディスク上の)ログファイル内にVirtual Log Files(VLF)を割り当てる。VLFはリングバッファから割り当てられ、数千個に達することもある。

  • この機能がまだリリースされていないことはわかる。

  • WALはデータ整合性を保ち、クラッシュからの復旧を助けるために存在するのだとずっと思っていた。しかしファイル自体はバッチで書き込まれ(ディスクへ信頼できる形でコミットされ)、それもデータベースの変更ごとではなく、性能を得るためにそうしている。これはその目的を損なわないのだろうか? データベース一般の話として、これに対する答えを見つけられなかった。

  • これがLitestreamのような新しい分散SQLiteシステムにどんな影響を与えるのか気になる。

  • つまり基本的には、データベースのためのダブルバッファリングということか? 納得できる。

  • WAL2モードはHC-treeバックエンド研究のベンチマークに含まれていた。