SQLiteで同時書き込みエラーを防ぐ方法があるのか探ってみました。 | 在宅ネットでコツコツお金を稼ぐ

データベースのSQLiteを使うようになって、その使い勝手がかなり気に入っています。 別のサイトではMySQL も使っているのですが、 SQLiteの使いやすさがとても良くて、動作もかなり軽快になっています。

イメージとしてはコンパクトカーのような、快適さがあります。

そこで、今後作るサイトは、SQLiteで作っていきたいと考えていますが、 一つ気になるのがSQLiteの機能面のことです。

SQLiteとMySQLの違いとして、 同時書き込みの際の処理、というのがあるようです。

MySQLは同時書き込みに非常に強くできていて、 ユーザーがサイトを訪れた際、データベースに書き込みをする、というような場合、 同時にMySQLに書き込みをする処理が動く場合、 こういった場合でもエラーを表示することなく、処理してくれます。

MySQLは非常に堅牢で高性能と言われていますが、 MySQLの強さというのは、こう言ったところにも表れているようです。

一方、SQLiteでは、同時書き込みに弱いという評判があるようです。

できれば、データベースを使うサイトはSQLiteに置き換えてみたいところですが、 同時書き込みでエラーが出るというのは少し困りますね。

例えば、私は作ったことがありませんが掲示板サイトを作って 運営しようと言った場合に、 たくさんのユーザーが掲示板に書き込みをすることになります。

ユーザーが掲示板に書き込みをする時に、 他のユーザーも同時に書き込みをしていた場合、 データベースへの書き込みの処理が重なってしまいます。

SQLiteの場合はその際にエラーが出るのではないか、ということでした。

SQLiteで書き込み中はどうなるのか実験

SQLiteで書き込みをした際にデータベースにアクセスするとエラーになるのかという の実験してみました。

プログラムA では、大量にSQLiteのデータベース(test.db)に書き込み(insert)をする プログラムを動かしてみます。 データベースに書き込みが終わるまで、 数十秒ぐらいかかるようなプログラムにしておきます。

プログラムB では、とりあえずtest.dbにselectだけを発行する、 ものにしておきました。

ブラウザを二つ起動して、ブラウザAはプログラムAを表示させます。 その書き込み処理が終わらない間に、 もう一つのブラウザBでプログラムBを表示させます。

すると、ブラウザBには、

Warning: SQLite3::query(): Unable to prepare statement: 5, database is locked in C:~.php on line 8

というメッセージが表示されました。

やはりデータベースファイル(test.db)に書き込みをしている際に、 同じデータベースファイル(test.db)にアクセスがあると

database is locked

というふうに、 ロックがかかってエラーが表示されるようです。

タイムアウト設定

ブログなどのように、データベースに書き込みをする人が管理人だけ、 という場合でしたらデータベースの書き込み処理が重ならないのでエラーの 心配はありませんが、書き込みする人が複数になると、 エラーが出てしまう心配があります。

解決方法としては、掲示板サイトなどのようにデータベースに 書き込み処理が複数に重なるようなサイトはMySQLを使うという方法もあると思いますが、 SQLiteでもできないのだろうかと、考えてみました。

インターネットでヒントを探して見たところ、 タイムアウトというのを見つけました。

PDO::ATTR_TIMEOUT: タイムアウト秒数を指定する。

PDO::setAttribute

私が使っているのは PHP なので PHP の関数になりますが、 PDOの場合は、テイムアウトの設定をするATTR_TIMEOUTというものがあります。

SQLite 関数の場合は

sqlite_busy_timeout:

になると思います。 この関数を使うことで、書き込み処理を行っている際は、 その処理を待ってくれるというものです。

実際のプログラムは、

$pdo = new PDO($dbstate);

となどといった具合に接続したあとに、

$pdo->setAttribute(PDO::ATTR_TIMEOUT,60);

というように追加書き換えました。 これで60秒待ってくれます。

確か、ミリセカンドではなくて、秒数で良かったと思いますが、 環境によってミリセカンドと秒数と異なるかもしれません。

ミリセカンドの場合は60秒だと、60000でしょうか。

そして、 再び先ほどと同じプログラムを動かしてみます。

プログラムAをブラウザAで表示させて、大量の書き込み処理をして、 ビジー状態になっているあいだに、

プログラムBを別のブラウザBで表示させます。

すると今回は、砂時計マークが出て待機状態になっています。 そしてブラウザAの処理が終わった後に、ブラウザB も表示されました。

こうすることで、エラーが出ることなくSQLiteへの同時書き込みができそうです。 ただ、数秒待つことになるので、プログラムの処理時間というのが気になります。

レンタルサーバーによっては長く時間がかかるプログラムは 禁止されていることがあるかもしれません。 この辺がレンタルサーバーの規約に違反してしまうのかどうか、 ちょっとよく分かりません。

規約の違反にならないようであれば、この方法を使うことで SQLiteの活用範囲が広がるように思います。

今回のまとめ

今回はSQLtiteの同時書き込みエラーを防ぐ方法を探してみました。 これでうまくいくと良いのですが、実戦配備してテストしてみないと わからないのがつらいところです。PHPですと、 PDOにしておいて、SQLiteでテスト 、もしもうまくいかなかった場合はすぐにMySQLに変更するというのも 良いのかもしれません。

データベースはうまく使えば、サイトのコンテンツをパワーアップ させることができますね。その中でもSQLiteはすごく使いやすいので、 今後も勉強していきたいと思います。

(2018/6/18)

トップページ

その他のコラム

コンテンツ

トップページ