我有一个 Perl 程序,在过去两年里我们每天都成功运行,但今天崩溃并显示错误消息:
致命错误:无法执行 PRAGMA cache_size = 1000000:尝试写入只读数据库
有问题的 SQLite 数据库是只读的,并且一直都是,并且代码始终使用PRAGMA cache_size = 1000000
打开其只读连接后立即对其进行操作。
设置cache_size不是写操作,如果我直接通过DBI访问数据库也不会失败,如下所示:
$dbh->do("PRAGMA cache_size = 1000000")
但是,代码使 SqliteH::db 成为 DBI::db 的子类,然后从子类调用此函数:
$self->SUPER::do("PRAGMA cache_size = 1000000")
现在它因“DBD::SQLite::db 失败:尝试在 /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。
请不要再次将标题更改为“运行了几个月的程序突然出错”。这是一个无益且不具体的标题。
TL;DR - 如果事务已开启,则任何命令都会尝试写入事务日志。如果数据库是只读的,请从 dbh 连接标志中删除 AutoCommit=>0 [您也不应该有任何 ->begin_work() 或 INSERT/UPDATE 调用,但这永远不会在只读数据库上工作:-) ] 。
事实证明,我今天在更新 SQLite、DBI 和 DBD::SQLite 后遇到了完全相同的问题(所以我不知道到底是哪一个导致了问题),但就我而言,是在 select 上(这使得它更令人费解)。
事实证明,事务是在原始连接字符串中打开的:
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 标志解决了我的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)