はじめまして。
この度ユーザーの所にシステムを導入するに当たり、
SQLite3を利用したサーバー/クライアント型のシステムを制作しようと思っています。
SQLiteはサーバー/クライアント型には向いていないのは分かっているのですが、なんとか上手く運用出来ない物かと考えていますが、
SQLiteを使用するが初めてなもので四苦八苦してます。
そこでまずは可/不可を判定する為にテストPGを作成し、
クラサバ環境で実行してみた所「database is locked」のエラーが発生してしまいます。
環境は
Delphi XE4
FireDacにて接続
SQLite3(3.8.10.2)
DBはサーバー側に配置し、フォルダに共有
仕様としては
1.PG起動時にADConnectionにてDBファイルに接続
2.テーブル(仮にTEST_TBL)をDBGridで表示
3.行ダブルクリックでレコード情報を画面に表示
4.確定ボタン押下で書き込み(この時トランザクションBEGIN〜COMMITしてます)
ADConnectionをConnectする際の設定値は
with ADOTEST do
begin
Open('DriverID=SQLite;'
+ 'Database=\\10.XXX.XXX.XXX\HOYASQL.DB3;'
+ 'AuthMode=Normal;'
+ 'BusyTimeput=100000;'
+ 'SharedCache=False;'
+ 'LockingMode=Normal;'
+ 'Synchronous=Normal;'
+ 'JournalMode=Truncate');
TxOptions.AutoCommit := True;
TxOptions.Isolation := xiReadCommitted;
UpdateOptions.LockWait := True;
UpdateOptions.LockMode := lmPessimistic;
UpdateOptions.LockPoint := lpImmediate;
end;
以下手順の時、
1.サーバーでPG実行
2.クライアントでもPG実行
3.クライアントでDBGridダブルクリック
4.サーバーでDBGridダブルクリック
5.サーバー側で確定ボタン押下
→ここでロックがかかって止まってしまう。
クライアント側で確定すれば進みます。
上記の現象後は、同処理を行ってもロックがかかりません。
ちなみに
1.サーバーでPG実行
2.クライアントでもPG実行
3.サーバーでDBGridダブルクリック
4.クライアントでDBGridダブルクリック
5.クライアント側で確定ボタン押下
→ここでロックがかかって止まってしまう。
サーバー側で確定すると「database is locked」が即座に表示されます。
やはりデータベースファイル単位でロックがかかっているから不可なのか、
設定がよろしくないのか、色々調べてみたのですが分かりませんでした。
引き続き私の方でも調査はしてますが、
どなたかご存知の方いらっしゃいましたらご教示願います。
記入忘れです。
知りたいのは、何故上記前述の方の確定処理時にロックがかかり、以降はかからなくなるのかが分からないんです。
> SQLiteはサーバー/クライアント型には向いていないのは分かっているのですが
とのことですが、
FireDAC での SQLite の使用
http://docwiki.embarcadero.com/RADStudio/Seattle/ja/FireDAC_%E3%81%A7%E3%81%AE_SQLite_%E3%81%AE%E4%BD%BF%E7%94%A8
にある
1.5 SQLite に向かない適用方法
http://docwiki.embarcadero.com/RADStudio/Seattle/ja/FireDAC_%E3%81%A7%E3%81%AE_SQLite_%E3%81%AE%E4%BD%BF%E7%94%A8#SQLite_.E3.81.AB.E5.90.91.E3.81.8B.E3.81.AA.E3.81.84.E9.81.A9.E7.94.A8.E6.96.B9.E6.B3.95
からすると、
やはり、SQLite以外のものも検討してみるのは、いかがですか?
>>igy様
ご回答ありがとうございます。また返信が遅くなり申し訳ありませんでした。
やはりそうですよね・・・。
私も当サイト他色々と調べてみましたが、同じような事が書かれていました。
他MySQL・PostgressSQLなども候補にはあがったのですが、
現ユーザー環境にインストールを必要とするツールを導入したくはなかったので、ファイルベースのDBをと検討していました。
前提に載せずに申し訳ありませんでした。
Accessも視野に入れてみたのですが、色々と制限(ファイル容量が4GBまで、文字列長が256バイトまでなど)が多く、過去の失敗からAccessも除外していました。
Firebirdなるものもあったのですが、どうやらこれもインストールが必要そうで・・・。
運用面でカバーする方法でなんとか競合を回避していく事になりそうです。
構成としては(1テーブル1DB)
1.上記グリッドに表示するDB「AAA.DB3」
2.PG使用中かどうかのDB「BBB.DB3」
非常に初歩的な回避ですが、
1.を誰かが使っている場合は2.に使用中のデータ・フラグを立て、
他の人が使用するとしたら2.のフラグが立っているので使用出来ないようにする。
このやり方だと複数人での実行は出来ないのですが、致し方ないですね。
貴重なご意見ありがとうございました。
> Firebirdなるものもあったのですが、どうやらこれもインストールが必要そうで・・・
Firebird でクライアント側に必要なのは DLL 一つだけです。
サーバ側はインストール (または ZIP 解凍&Install???.bat 実行) が必要ですが。
http://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=1255.0
既に解決済みですが、明確な原因が分かりました。
FireDacのオプション設定で
ADConnection.FetchOptions.Modeが関係していて、これの値の初期値が「fmOnDemand」だったのが原因でした。
RowsetSize=50が初期値+「fmOnDemand」の場合、レコード取得が50件毎に取得する状態で、NextRecordが実行されると再度取得に次の50件取得が走るようです。
(RecordCountを調べた時に気づきました)
これを「fmAll」にし、一度のSQLで全件取得出来るようにしただけで、「database is locked」が表示されなくなりました。
複数端末で同時に書き込みを行ったところ、早い方の書き込みが終わるまで遅い方は待ち状態になるので、狙った通りの動きになってくれました。
なぜレコード取得の状態でロックがかかるのかは現在調査中です。
私は、趣味でDBを扱うAPPを作成しています。
当初、SQLiteを使用することも試しましたが、癖が強くやめてしまいました。
今は、Firebirdの組込み版を利用しています。これはDEKOさんも述べているように
DLLを一つ追加するだけで、特にDBのインストールをせずに使えます。
ユーザーは、通常のAPPのインストールをするだけでOKですのでGoodです。
Firebirdを推薦します。
ツイート | ![]() |