2つのPythonプロセスがアクセスするSQLite:1つの読み取り、1つの書き込み


22

私は2つのコンポーネントを持つ小さなシステムを開発しています。1つはインターネットリソースからデータをポーリングし、それをsqlデータに変換してローカルに保持します。2番目のものは、ローカルインスタンスからそのsqlデータを読み取り、jsonおよびrestful apiを介して提供します。

私はもともとpostgresqlでデータを永続化することを計画していましたが、アプリケーションには保存するデータとサービスするトラフィックの量が非常に少ないため、やり過ぎだと思いました。SQLiteは仕事をしているのですか?フットプリントが小さく、この1つのタスクのために別のSQLサーバーを維持する必要がないというアイデアが大好きですが、同時実行性が心配です。

先読みロギングを有効にすると、データベースからプロセスをロックアウトせずに、SQLiteデータベースの読み取りと書き込みを同時に行うことができるようです。

1つの読み取りと他の書き込みのみが行われる場合、単一のSQLiteインスタンスは、それにアクセスする2つの並行プロセスを維持できますか?私はコードを書き始めましたが、これがSQLiteの誤用かどうか疑問に思っていました。


3
@gnatクール。1つの読み取りと他の書き込みのみの場合、単一のSQLiteインスタンスは、それにアクセスする2つの並行プロセスを維持できますか?私はコードを書き始めましたが、これがSQLiteの誤用かどうか疑問に思っていました。
bb

ただ頭を上げます。私の前の会社では、一部のストレージにSQL(MSとOracle Expressの両方)を使用していましたが、格納するデータが少ないため、完全なDBは必要ないと常に感じていました。そのため、リリースの1つで、あなたがしていることを正確に行うことにしました。これらの製品をSQLiteに置き換えます。ディスク上にデータを配置し、SQLベースのTOCを更新するライターと、TOCを読み取って取得するデータを決定するリーダープロセス(複数のスレッド)を更新するライターが1つありました。最近のSQLiteについては知りませんが、私たちが遭遇したわずかな並行性は、大きな苦痛であることが判明しました
...-DXM

...後ろに。すべての詳細を覚えているわけではありませんが、あるプロセスがロックを取得しようとして、別のプロセスが読み取り中だったために取得できなかった場合、20〜30秒のような異常な時間スリープします。最終的に、SQLiteアクセスを担当する専用スレッドを作成し、プロセスとその中のすべてのスレッドの両方で、DBリクエストをその1つのスレッドにシリアル化しました。後から考えると、おそらくSQLiteを再び使用することはなかったでしょう。
DXM

1
@DXMは警告に感謝しますが、いくつかのテストを実行した後、私は同様のものに対して実行していません。sqliteは2004年頃のバージョン3で大幅なオーバーホールを受けたので、その前にネガティブな経験があったのではないかと思います。
bb

1
... SQLiteのロックスキームに依存するのではなく、自分で。私は自分で仕事をしませんでした。別のチームでしたが、主にフィードバックを提供し、好奇心をそそるためにループを続けました。私もオンラインに行き、いくつかの独立した読書をして、元の著者のページを見つけました。それを読んで、SQLiteの発明者は単にスレッドを嫌い、だれもスレッドを使用しない理由がわからなかったという印象を受けました。あまりにも多くの人がそれを求めたため、後付けとしてハッキングされました。
DXM

回答:


25

ファイルのロックと同時実行のドキュメントを探しています

SQLiteプロセスは一連のロックを使用して並行性を処理します。読み取るために、いくつかのプロセスがSHAREDロックを取得できます。

書き込みを行うプロセスはRESERVEDロックを取得する必要があり、実際に変更をディスクにフラッシュする必要がある場合にのみ、PENDING状態に移行します。その後、読み取りプロセスはファイルのロックを解除する必要があります。その後、書き込みプロセスはEXCLUSIVE実際のデータベースファイルへの書き込みに移動できます。

ライタープロセスは、実際の書き込み(メモリフラッシュ、コミット)のためにデータベースファイルをロックするだけでよいため、リーダーが1つだけでライターが1つだけのセットアップは非常にうまく機能します。1つのプロセスだけですべての読み取りと書き込みを実行するセットアップとして、パフォーマンスが良くないにしても、同じように機能すると期待しています。

SQLiteは、PENDING変更をシリアル化するために排他ロックを取得する必要があるため、同じデータベースに頻繁に書き込む複数のプロセスがある場合にはあまり適していません。


Martijnの徹底的な回答に感謝します!私はいくつかのテストを行うスクリプトをいくつか作成しましたが、2つのプロセスが単一のsqliteインスタンスを同時に読み書きできるようです。100分の1秒ごとに起動する同時読み取りおよび書き込み要求を行っていましたが、ロックされたdb例外を受信しませんでした。奇妙なことに、「データベースがロックされました」というエラーメッセージが表示されたのは、読み取り要求がスクリプトから100分の1秒で実行されている間に、手動で(sqlite3コマンドラインクライアントで)数行を削除しようとしたときだけでした。pysqlはそのようなエラーの後に自動的に書き込みを再試行するのだろうか。
bb

10

フォローアップして、実装が成功したことを全員に知らせたかっただけです。SQLiteを使用することは本当に喜びであり、一度に1つのプロセスだけで書き込みを行うことで、ロックアップの問題が発生することはありませんでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.