2013-07-22 55 views
1

时设置的SQLite数据库CACHE_SIZE作为写操作我有一个我们每天都成功运行了差不多过去的2年一个Perl程序,但今天它崩溃,并显示错误消息:Perl的DBI对待继承DBI

严重错误:不能做PRAGMA CACHE_SIZE = 1000000:尝试写入只读数据库

有问题的SQLite数据库是只读的,而且一直是,并且代码始终打开后立即使用PRAGMA cache_size = 1000000就可以了其只读连接。

设置CACHE_SIZE不是写操作时,如果我直接访问数据库直通的DBI,这样不会失败:

$ dbh->做( “PRAGMA CACHE_SIZE = 1000000”)

然而,该代码使得SqliteH :: DB DBI ::数据库的一个子类,然后调用从子类此功能:

$自我> SUPER :: DO( “PRAGMA CACHE_SIZE = 1000000”)

和它现在与“DBD :: SQLite :: db失败:试图写只读数据库se位于/local/ifs_projects/prok/function/src/lib/SqliteH.pm第329行。“

该代码与CentOS 5,Perl 5.10.1,DBD :: SQLite 1.29和DBI 1.611一起工作。 它不起作用CentOS 6,Perl 5.16,DBD :: SQLite 1.39和DBI 1.627。 但是,我很困惑,它/上周在CentOS 6和Perl 5.16上工作。 IT可能在周末升级了DBD :: SQLite或DBI。

请不要将标题改为“再次运行数月的程序中突然出现错误”。这是一个无益的和非特定的标题。

+0

改变了什么? Perl版本? –

+0

您的硬盘是否已满(或任何硬盘)?如果它是一个虚拟机,并且它被过度配置,您将不得不检查虚拟机主机。 – tgolisch

+0

硬盘未满。我已经在3个不同的CentOS 6服务器上测试过它,并且它们都以相同的方式失败。它从DBI.pm的代码看来,DBI的子类化在新的DBI中处理方式不同。一个可能的线索是,错误消息说“DBD :: SQLite :: db失败”,而我期待它执行DBI :: db做。 –

回答

3

TL; DR - 如果事务处于打开状态,则任何命令都会尝试写入事务日志。如果数据库是只读的,请从dbh连接标志中删除AutoCommit => 0 [您不应该有任何 - > begin_work()或INSERT/UPDATE调用,但是这只对只读数据库没有效果:-)] 。

事实证明,在更新SQLite,DBI和DBD :: SQLite之后,我发现了完全相同的问题(所以我不知道它们究竟是哪个导致了问题),但在我的情况下, (这使得它更令人困惑)。 原来,交易是在原来的连接字符串打开:

my $dbh=DBI->connect('dbi:SQLite:file.db','','',, {PrintError=>1,RaiseError=>1,AutoCommit=>0}); 

,并跟踪代码后,我发现它实际上是崩溃试图启动一个事务。

DB<4> $dbh->trace(15) 
    DBI::db=HASH(0x18b9c38) trace level set to 0x0/15 (DBI @ 0x0/0) in DBI 1.627-ithread (pid 15740) 
    DB<5> $sth= $dbh->prepare("SELECT key,value FROM annotation where accession=?") 
    ... 
    DB<6> $sth->execute('D3FET3') 
    -> execute for DBD::SQLite::st (DBI::st=HASH(0x18ba340)~0x18ba178 'D3FET3') thr#10cd010 
    sqlite trace: bind into 0x18ba268: 1 => D3FET3 (0) pos 0 at dbdimp.c line 1232 
    sqlite trace: executing SELECT key,value FROM annotation where accession=? at dbdimp.c line 660 
    sqlite trace: bind 0 type 3 as D3FET3 at dbdimp.c line 677 
    sqlite trace: BEGIN TRAN at dbdimp.c line 774 
    sqlite error 8 recorded: attempt to write a readonly database at dbdimp.c line 79 
     !! ERROR: '8' 'attempt to write a readonly database' (err#1) 
     <- execute= (undef) [1 items] at (eval 15)[/usr/local/packages/perl-5.16.1/lib/5.16.1/perl5db.pl:646] line 2 via at -e line 1 
    DBD::SQLite::st execute failed: attempt to write a readonly database at (eval 15)[/usr/local/packages/perl-5.16.1/lib/5.16.1/perl5db.pl:646] line 2. 
    ... 

删除connect()调用中的AutoCommit => 0标志修复了我的问题。

+0

你已经救了我,A.里希特! –

+0

更新:更改内容为:(来自http://cpansearch.perl.org/src/ISHIGAKI/DBD-SQLite-1.39/Changes) ... 1.38_01 2012年9月24日星期一 ***可能发生的变化可能会中断您的旧应用程序*** - 已解决#56444:应立即执行交易,默认为 ,并更新文档。 如果您确实需要延迟交易(默认长度为 ),请将sqlite_use_immediate_transaction 设置为false。 (ISHIGAKI) –