3

次の Perl コードを検討してください。

#!/usr/env/ perl
use strict;
use warnings;
use DBI;

my $filename = 'moo.sqlite';
my $dbh = DBI->connect("dbi:SQLite:dbname=$filename","","");
my $sql = 'INSERT into moo values (1)';
my $sth = $dbh->prepare( $sql );
my $rv = $sth->execute();
print $rv;

実行すると次のエラーが発生します。

DBD::SQLite::db prepare failed: disk I/O error at test.pl line 16.
Can't call method "execute" on an undefined value at test.pl line 18.

SQLite ファイルは、SMBFS/CIFS ネットワークにマウントされた共有にあります。

いくつかのトレースを行ったところ、ファイルをロックしようとしたときにエラーが発生したようです。

open("moo.sqlite\0", 0x202, 0x1A4)       = 3 0
fcntl(0x3, 0x1, 0x0)         = 0 0
fcntl(0x3, 0x2, 0x1)         = 0 0

ネットワーク ロックに問題があることは理解していますが、'sqlite3' バイナリを対話的に実行すると同じ問題が発生しませんか? 現在、問題なくファイルを操作できます。

これは DBI が原因ですか?

ご参考までに:

  • OS X 10.6.8
  • SQLite バージョン 3.7.13
  • パール 5.12.4
  • DBI 1.622
  • DBD::SQLite 1.37
4

1 に答える 1

2

SQLite では、複数のプロセスでデータベース ファイルを一度に開いたり、複数のプロセスでデータベースを一度に読み取ったりすることができます。プロセスが書き込みを行う場合、更新中はデータベース ファイル全体をロックする必要があります。しかし、通常は数ミリ秒しかかかりません。他のプロセスは、ライターが完了するのを待ってから、処理を続行します。他の組み込み SQL データベース エンジンでは、通常、データベースに一度に接続できるプロセスは 1 つだけです。

あなたはこれを試すことができます、それは役立つかもしれません:

my $dbh = DBI->connect("dbi:SQLite:dbname=$filename","","", "", "", {
  sqlite_use_immediate_transaction => 1,
});

問題は、CIFS ドライバーがロックを尊重/許可するように構成できることです。その部分が正しく構成されていないと、ロックが機能しません。

Samba のロック設定を変更してみてください: http://oreilly.com/openbook/samba/book/ch05_05.html

試してみるのに最適な候補: "fake oplocks = yes"

うまくいかない場合は、Windows マシンで ODBC データソースをセットアップし、それを介してデータベースにアクセスしてみてください。

于 2012-10-30T15:41:53.887 に答える