2010-10-15 12 views
6

SQLite, Perl DBD :: SQLite kullanırken tek bir işlemde ikinci bir sorgu için "veritabanı kilitli" hatası veren SQLite ile ilgili bilinen bir sorun mu var? Senaryo: Linux, Perl DBI, AutoCommit => 0, iki kod bloğu olan bir altprogram (değişken adlarını yerelleştirmek için blokları kullanarak). Birinci kod bloğunda, bir select deyimi üzerinde hazırla() tarafından bir sorgu tutamacı oluşturulur, yürütülür() ve blok kapatılır. İkinci kod bloğu, başka bir sorgu tanıtıcısı bir güncelleme deyimi için hazırlanır ve sık sık (zamanın% 30'u) SQLite/DBI, bu aşamada veritabanı kilitli bir hata verir. Ben hata(), execute() sırasında değil, hazırlanma sırasında olduğunu düşünüyorum.Perl'in DBD :: SQLite kullanıldığında, SQLite neden işlemin ikinci bir sorgu için "veritabanı kilitli" olduğunu gösteriyor?

Benim çalışmam ilk sorgudan sonra işlemek. (İlk sorguda arama bitirme yardım etmedi). Zarafet ve performansla ilgili birkaç nedenden dolayı taahhüt etmemeyi tercih ediyorum. Orijinal kod, Postgres ile uzun yıllar boyunca veri tabanı olarak iyi çalıştı. Efekti olmadan sqlite_use_immediate_transaction denedim.

Diğer tüm durumlarda, SQLite'i çok iyi bir performans sergileyecek şekilde buldum, bu yüzden bunun SQLite ile ilgili bir sorundan ziyade DBD sürücüsündeki bir gözetim olduğundan şüpheleniyorum. Ne yazık ki, şu anki kodum çok sayıda komut dosyası ve modül yığınıdır, bu yüzden kısa, tek bir dosya test vakam yok.

+0

Sorunu gösteren küçük test durumunuzu bize gösterebilir misiniz? –

cevap

6

Bununla ilgili olmayanlar: Transaction and Database LockingDBD::SQLite perldoc?

AutoCommit veya begin_work tarafından yapılan işlem güzel ve kullanışlıdır, ancak bazen can sıkıcı bir "veritabanı kilitli" hatası alabilirsiniz. Bu genellikle bir kişi bir işlem başlattığında ve diğer kişi veritabanından (başka bir işlemde) okurken bir veritabanına yazmaya çalışırsa gerçekleşir. Şaşırmış olabilirsiniz, ancak eşzamanlılığı en üst düzeye çıkarmak için normal (ertelenmiş) bir işlem başlattığınızda SQLite bir veritabanını kilitlemez. Yazmak için bir ifade verdiğinizde bir kilit saklar, ancak aslında bir taahhüt ifadesi ile yazmaya çalışana kadar, diğer kişilerin veritabanından okumasına izin verir. Ancak, veritabanından okuma da paylaşılan kilit gerektirir ve size ayrılan size özel kilit vermek için engeller, böylece "veritabanı kilitli" hatası alırsınız ve diğer insanlar, daha sonra yazmayı denerseniz, aynı hatayı alacaksınız Hala bekleyen bir kilit var. meşgul_timeout bu durumda yardımcı olmaz.

Bunu önlemek için, işlem türünü açıkça ayarlayın. Her işlem için hemen bir işlem başlatabilir (veya özel işlem başlatabilir) veya sqlite_use_immediate_transaction veritabanı tanıtıcısı özelliğini her zaman bir ani işlem (her zaman başlangıç ​​işini kullandığınızda veya Otomatik İşlevi kapattığınızda bile) kullanmak için true (1.30_02'den beri) olarak ayarlayabilirsiniz. .

my $dbh = DBI->connect("dbi:SQLite::memory:", "", "", { 
    sqlite_use_immediate_transaction => 1, 
}); 
bağlantılarının hepsi aynı (non-ertelenmiş) işlem kullandığınızda bu sadece çalışır

Not. Kilitleme detayları için bkz. http://sqlite.org/lockingv3.html.