sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Bunun çalışması için veritabanının kilidini nasıl açabilirim?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Bunun çalışması için veritabanının kilidini nasıl açabilirim?
Yanıtlar:
Windows'da bu programı deneyerek http://www.nirsoft.net/utils/opened_files_view.html deneyerek işlemi db dosyası ile çalıştığını öğrenebilirsiniz . Veritabanı kilidini açmak için bu programı kapatmayı deneyin
Linux ve macOS'ta, örneğin kilitli dosyanız development.db ise benzer bir şey yapabilirsiniz:
$ fuser development.db
Bu komut, dosyayı hangi işlemin kilitlediğini gösterecektir:
> development.db: 5430
Sadece süreci öldür ...
öldür -9 5430
... Ve veritabanınızın kilidi açılacak.
kill
zaman iyi olmalı, ancak düzgün bir şekilde öldürmeye dikkat etmelisiniz ve kill -9
muhtemelen yanlış ve / veya aşırı derecede. İşlem asılırsa ve başka türlü ölmezse, bazen ihtiyacınız olur kill -9
. Ancak, ana üretim işine gitmek ve onu öldürmek istemezsiniz, böylece veritabanının artık kilitli olmadığını bildirebilirsiniz!
Benim sqlite db yazma sırasında bir uygulama çökerek kilitli neden oldu. İşte nasıl düzelttim:
echo ".dump" | sqlite old.db | sqlite new.db
Alındığı yer: http://random.kakaopor.hu/how-to-repair-an-sqlite-database
sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; /**** ERROR: (5) database is locked *****/ ROLLBACK; -- due to errors
FOREIGN KEY constraint failed (RELEASE RESTOREPOINT)
Aşağıda listelenen DatabaseIsLocked sayfası artık mevcut değil. Dosya Kilitleme ve Eşzamanlılık sayfası, v3'te tanıtılan dosya kilitleme ile ilgili değişiklikleri açıklar ve gelecekteki okuyucular için yararlı olabilir. https://www.sqlite.org/lockingv3.html
SQLite wiki DatabaseIsLocked sayfası bu hata mesajının iyi bir açıklamasını sunar. Kısmen, çekişme kaynağının dahili olduğunu (hatayı yayan sürece) belirtir.
Bu sayfanın açıklamadığı şey, SQLite'nin işleminizdeki bir şeyin bir kilidi tuttuğuna ve hangi koşulların yanlış pozitifliğe yol açabileceğine nasıl karar verdiğidir.
-Dergi dosyasını silmek korkunç bir fikir gibi geliyor. Bir çökme sonrasında sqlite'ın veritabanını tutarlı bir duruma geri döndürmesine izin vermek için orada. Veritabanı tutarsız bir durumdayken silerseniz, bozuk bir veritabanı kalır. Sqlite sitesinden bir sayfaya atıf :
Bir kilitlenme veya güç kaybı meydana gelirse ve diskte bir sıcak günlük kalırsa, veritabanı dosyası başka bir SQLite işlemi tarafından açılana ve geri alınana kadar, özgün veritabanı dosyasının ve sıcak günlüğün orijinal adlarıyla diskte kalması önemlidir. . [...]
SQLite kurtarma için ortak bir hata modunun şu şekilde gerçekleştiğinden şüpheleniyoruz: Bir elektrik kesintisi meydana gelir. Güç geri yüklendikten sonra, iyi niyetli bir kullanıcı veya sistem yöneticisi diskte hasar olup olmadığına bakmaya başlar. Veritabanı dosyasını "important.data" olarak görürler. Bu dosya belki de onlara tanıdık geliyor. Ancak çarpışmadan sonra "important.data-journal" adında sıcak bir dergi de var. Kullanıcı daha sonra sistemi temizlemeye yardımcı olduğunu düşünerek sıcak günlüğü siler. Bunu önlemek için kullanıcı eğitimi dışında bir yol bilmiyoruz.
Geri alma işlemi, veritabanı bir sonraki açılışında otomatik olarak gerçekleşir, ancak işlem veritabanını kilitleyemezse başarısız olur. Diğerlerinin söylediği gibi, bunun olası bir nedeni şu anda başka bir sürecin açık olmasıdır. Başka bir olasılık, veritabanı bir NFS birimindeyse eski bir NFS kilididir. Bu durumda, geçici çözüm, veritabanı dosyasını NFS sunucusunda kilitli olmayan yeni bir kopyayla (mv database.db original.db; cp original.db database.db) değiştirmektir. Sqlite SSS'nin, NFS dosya kilitlemesinin hatalı uygulamaları nedeniyle NFS birimlerindeki veritabanlarına eşzamanlı erişim konusunda dikkatli olmanızı önerdiğini unutmayın.
Bir dergi dosyasını silmenin neden daha önce yapamayacağınız bir veritabanını kilitlemenize izin vereceğini açıklayamıyorum. Bu tekrarlanabilir mi?
Bu arada, bir dergi dosyasının varlığı mutlaka bir çökme olduğu veya geri alınacak değişikliklerin olduğu anlamına gelmez. Sqlite birkaç farklı günlük moduna sahiptir ve PERSIST veya TRUNCATE modlarında -journal dosyasını her zaman yerinde bırakır ve geri alınacak kısmi işlem olup olmadığını göstermek için içeriği değiştirir.
"Veritabanı kilitli" hatasını kaldırmak istiyorsanız şu adımları izleyin:
Bir işlemin bir SQLite DB'sinde bir kilit varsa ve çökerse, DB kalıcı olarak kilitli kalır. İşte sorun bu. Başka bir işlemin kilidi olmadığı anlamına gelmez.
SQLite db dosyaları sadece dosyalardır, bu nedenle ilk adım salt okunur olmadığından emin olmak olacaktır. Yapılması gereken diğer bir şey, DB açıkken GUI SQLite DB görüntüleyicisinin bir tür olmadığından emin olmaktır. DB başka bir kabukta açık olabilir veya kodunuz DB açık olabilir. Farklı bir iş parçacığı veya SQLite Veritabanı Tarayıcısı gibi bir uygulama DB yazmak için açıksa genellikle bunu görürsünüz.
Ben şimdi, NFS mount saklanan uzak bir sunucuda bir SQLite veritabanı kullanarak bu sorunu vardı. SQLite veritabanı açıkken kullandığım uzak kabuk oturumu çöktükten sonra kilit alamadı.
Yukarıda önerilen kurtarma tarifleri benim için işe yaramadı (önce veritabanını geri taşıyıp sonra geri kopyalamak fikri dahil). Ancak bunu NFS olmayan bir sisteme kopyaladıktan sonra, veritabanı kullanılabilir hale geldi ve veri kaybedilmemiş gibi görünüyor.
Kilidim sistemin kilitlenmesi, asılı bir işlemden değil. Bunu çözmek için dosyayı yeniden adlandırdım ve orijinal adına ve konumuna kopyaladım.
Bir linux kabuğu kullanarak ...
mv mydata.db temp.db
cp temp.db mydata.db
Pooling=true
Bağlantı dizesine " " ekledim ve çalıştı.
SQLite çeşitli kilitleme durumlarının belgelerini çok yararlı buldum . Michael, okumaları gerçekleştirebilir ancak veritabanına yazma gerçekleştiremezseniz, bu, bir işlemin veritabanınızda REZERVED bir kilit aldığını, ancak henüz yazma işlemini gerçekleştirmediğini gösterir. SQLite3 kullanıyorsanız, daha fazla işlemin bağlanmasına izin verilmeyen ancak mevcut bağlantıların eşik değerleri okuma yapabileceği PENDING adlı yeni bir kilit var, bu yüzden bu sorun varsa bunun yerine bakmalısınız.
Ben uygulama içinde böyle bir sorun var, hangi SQLite erişim 2 bağlantı - bir salt okunur ve yazma ve okuma için ikinci oldu. Bu, salt okunur bağlantının ikinci bağlantıdan yazılmasını engellediği anlaşılıyor. Son olarak, hazırlanan ifadelerin kullanımdan sonra HEMEN bitirilmesi veya en azından sıfırlanması gerektiği ortaya çıkmaktadır. Hazırlanan ifade açılana kadar veritabanına yazılması engellendi.
ÇAĞRI UNUTMAYIN:
sqlite_reset(xxx);
veya
sqlite_finalize(xxx);
INDEX'ing gibi bazı işlevler çok uzun zaman alabilir - ve çalışırken tüm veritabanını kilitler. Böyle durumlarda günlük dosyasını bile kullanamayabilir!
Bu nedenle, veritabanınızın kilitli olup olmadığını kontrol etmenin en iyi / tek yolu, bir işlem ETKİN olarak ona yazdığı için (ve böylece işlemi tamamlanana kadar cehennemi yalnız bırakmanız gerekir) dosyayı iki kez md5 (veya bazı sistemlerde md5sum) . Farklı bir sağlama toplamı alırsanız, veritabanı yazılır ve gerçekten gerçekten -9 bu işlemi öldürmek istemezsiniz, çünkü eğer kolayca bozuk bir tablo / veritabanı ile sonuçlanabilir.
Tekrar edeceğim, çünkü önemli - çözüm kilitleme programını bulmak ve öldürmek DEĞİL - veritabanının iyi bir nedenden dolayı yazma kilidine sahip olup olmadığını bulmak ve oradan gitmek. Bazen doğru çözüm sadece bir kahve molasıdır.
Bu kilitli ama yazılmamış olan durumu yaratmanın tek yolu, programınızın çalışmasıdır BEGIN EXCLUSIVE
, çünkü bazı tablo değişiklikleri yapmak veya bir şey yapmak isterse, o zaman neden daha END
sonra hiç göndermezse ve süreç asla sona ermez . Karşılaşılan her üç koşul da uygun şekilde yazılmış herhangi bir kodda pek olası değildir ve birisi kilitleme işlemini -9'u öldürmek istediğinde 100'den 99'u gibi, kilitleme işlemi aslında veritabanınızı iyi bir nedenden dolayı kilitler. Programcılar, BEGIN EXCLUSIVE
gerçekten gerekmedikçe durumu eklemezler, çünkü eşzamanlılığı önler ve kullanıcı şikayetlerini artırır. SQLite sadece gerçekten ihtiyaç duyduğunda ekler (indeksleme gibi).
Son olarak, birkaç yanıtın belirttiği gibi dosyanın İÇİNDE 'kilitli' durumu yoktur - İşletim Sisteminin çekirdeğinde bulunur. BEGIN EXCLUSIVE
İşletim sisteminden kilit işlemi istenen dosyaya yerleştirilir. Özel işleminiz çökse bile, işletim sisteminiz dosya kilidini korumayı sürdürüp sürdürmeyeceğini anlayabilir! Kilitli bir veritabanı ile sonuçlanmak mümkün değildir, ancak hiçbir işlem aktif olarak kilitlemez !! Hangi işlemin dosyayı kilitlediğini görmek söz konusu olduğunda, kaynaştırıcıdan ziyade lsof kullanmak daha iyidir (bu nedeninin iyi bir gösterisidir: /unix/94316/fuser-vs-lsof- kullanımda dosyaları kontrol etmek için ). Alternatif olarak DTrace (OSX) varsa dosyada iosnoop kullanabilirsiniz.
Benim de benzer bir şey yaşadım - web uygulamam veritabanından okuyabildi, ancak herhangi bir ekleme veya güncelleme yapamadı. Apache'nin yeniden başlatılması sorunu en azından geçici olarak çözdü.
Bununla birlikte, temel nedeni takip edebilmek güzel olurdu.
Bu bağlantı sorunu çözer. : Sqlite verdiğinde: Veritabanı kilitli hatası Sorunum sizin için yararlı olabilir çözüldü.
Ve ileride veritabanını kilitli hale getirmemek için başlangıç işlemini ve son işlemi kullanabilirsiniz.
Bir veritabanının iç sorunu olmalı ...
Benim için "SQLite yöneticisi" ile veritabanına göz atmaya çalıştıktan sonra tezahür etti ...
Yani, başka bir işlem bulamazsanız veritabanına bağlanır ve düzeltemezsiniz, şu radikal çözümü deneyin:
rake db:migrate
" İle çalıştırAynı sorunu bir terminal oturumundan Python komut dosyalarını çalıştıran Mac OS X 10.5.7'de gördüm. Komut dosyalarını durdurmuş ve terminal penceresi komut isteminde oturmuş olsa da, bir dahaki sefere bu hatayı verecektir. Çözüm, terminal penceresini kapatmak ve tekrar açmaktı. Bana bir anlam ifade etmiyor, ama işe yaradı.
Ben de aynı problemi yaşadım. Görünüşe göre geri alma işlevi, db dosyasının db dosyasıyla aynı olan ancak en son değişiklik olmadan günlüğe yazdığını söylüyor. Aşağıdaki kodumda bu uyguladım ve o zamandan beri iyi çalışıyor, oysa benim kod sadece veritabanı kilitli kaldı gibi döngü içinde sıkışmış olur.
Bu yardımcı olur umarım
##############
#### Defs ####
##############
def conn_exec( connection , cursor , cmd_str ):
done = False
try_count = 0.0
while not done:
try:
cursor.execute( cmd_str )
done = True
except sqlite.IntegrityError:
# Ignore this error because it means the item already exists in the database
done = True
except Exception, error:
if try_count%60.0 == 0.0: # print error every minute
print "\t" , "Error executing command" , cmd_str
print "Message:" , error
if try_count%120.0 == 0.0: # if waited for 2 miutes, roll back
print "Forcing Unlock"
connection.rollback()
time.sleep(0.05)
try_count += 0.05
def conn_comit( connection ):
done = False
try_count = 0.0
while not done:
try:
connection.commit()
done = True
except sqlite.IntegrityError:
# Ignore this error because it means the item already exists in the database
done = True
except Exception, error:
if try_count%60.0 == 0.0: # print error every minute
print "\t" , "Error executing command" , cmd_str
print "Message:" , error
if try_count%120.0 == 0.0: # if waited for 2 miutes, roll back
print "Forcing Unlock"
connection.rollback()
time.sleep(0.05)
try_count += 0.05
##################
#### Run Code ####
##################
connection = sqlite.connect( db_path )
cursor = connection.cursor()
# Create tables if database does not exist
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS fix (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS tx (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS completed (fix DATE, tx DATE);''')
conn_comit( connection )
Bu istisnayı almanın yaygın bir nedeni, bir okuma işlemi için kaynakları tutarken bir yazma işlemi yapmaya çalışmanızdır. Örneğin, bir tablodan SEÇ, sonra da ResultSet'inizi kapatmadan seçtiğiniz bir şeyi GÜNCELLEMEYE çalışırsanız.
Ben görünüyor ki, hem çok dişli bir uygulama hataları "Veritabanı kilitli" başlamıştı SQLITE_BUSY sonuç kodu ve ben ayarı ile çözüldü sqlite3_busy_timeout uygun uzun 30000 gibi bir şey.
(Bir yan notta, 7 yaşındaki bir soruda kimse bunu şimdiye kadar bulamadı! SQLite gerçekten tuhaf ve şaşırtıcı bir proje ...)
Yeniden başlatma seçeneğine gitmeden önce, sqlite veritabanının kullanıcısını bulabileceğinizi görmek önemlidir.
Linux'ta fuser
bu amaçla kullanılabilir:
$ fuser database.db
$ fuser database.db-journal
Benim durumumda şu yanıtı aldım:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
Hangi veritabanı kullanarak pid 3556 (manage.py) ile başka bir Python programı olduğunu gösterdi.
Eski bir soru, çok sayıda cevabı olan, yukarıdaki cevapları okurken izlediğim adımlar burada, ancak benim durumumda sorun ciflerin kaynak paylaşımından kaynaklanıyor. Bu vaka daha önce bildirilmedi, umarım birine yardımcı olur.
Bağlantı açıklığındaki kilit modunu
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());
SQLite db dosyanızı bir NFS paylaşımlı klasörü üzerinde kullanıyorsanız, SQLite SSS'nin bu noktasını kontrol edin ve burada açıklandığı gibi kilitlerden kaçındığınızdan emin olmak için montaj yapılandırma seçeneklerinizi gözden geçirin :
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
Bu hatayı burada açıklananlardan biraz farklı bir senaryoda aldım.
SQLite veritabanı 3 sunucu tarafından paylaşılan bir NFS dosya sistemine dayanıyordu. Sunucuların 2'sinde veritabanında sorguları başarıyla çalıştırabildim, üçüncüsünde "veritabanı kilitli" mesajını aldığımı düşündüm.
Bu 3. makine ile ilgili bir şey, üzerinde boş alan kalmamasıydı /var
. Everytime ben bu dosya sisteminde bulunan HERHANGİ bir SQLite veritabanında bir sorgu çalıştırmak için çalıştı "veritabanı kilitli" mesajı ve ayrıca günlükleri üzerinde bu hata var:
Ağu 8 10:33:38 server01 çekirdek: lockd: izlenemiyor 172.22.84.87
Ve bu da:
Ağu 8 10:33:38 server01 rpc.statd [7430]: Eklenemedi: yazı /var/lib/nfs/statd/sm/other.server.name.com: Cihazda boşluk kalmadı 8 Ağu 33: 38 server01 rpc.statd [7430]: SM_MON için 172.22.84.87 için STAT_FAIL - sunucu01
Uzay durumu ele alındıktan sonra her şey normale döndü.
Eğer kilidini çalışıyorsanız Chrome veritabanını için SQLite ile görüntülemek , o zaman sadece Chrome'u kapatın.
pencereler
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Web Data
or
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Chrome Web Data
Mac
~/Library/Application Support/Google/Chrome/Default/Web Data
Önceki yorumlarınızdan bir dergi dosyasının olduğunu söylediniz.
Bu, işlemi açtığınız ve (ÖZEL?) İşlem yaptığınız ve henüz verileri işlemediğiniz anlamına gelebilir. Programınız ya da başka bir süreç -Geriyeti geride mi bıraktı ??
Sqlite işleminin yeniden başlatılması günlük dosyasına bakar ve taahhüt edilmeyen eylemleri temizler ve -journal dosyasını kaldırır.
Seun Osewa'nın dediği gibi, bazen bir zombi süreci, mümkün olduğunu düşünmeseniz bile, terminalde kilitli bir kilitle oturur. Komut dosyanız çalışıyor, çöküyor ve isteme geri dönüyorsunuz, ancak bir yerde bir kütüphane çağrısı tarafından ortaya çıkan bir zombi işlemi var ve bu işlemin kilidi var.
Bulunduğunuz terminalin kapatılması (OSX'te) işe yarayabilir. Yeniden başlatma işe yarayacaktır. Hiçbir şey yapmayan "python" süreçleri arayabilir ve onları öldürebilirsiniz.
bunu deneyebilirsiniz: .timeout 100
zaman aşımı süresini ayarlamak için. Komut satırında ne olduğunu bilmiyorum ama bunu yaptığımda C # .Net: "UPDATE table-name SET column-name = value;"
Veritabanı kilitli olsun ama bu "UPDATE table-name SET column-name = value"
iyi gidiyor.
Eklediğinizde gibi görünüyor;, sqlite daha fazla komut arayacaktır.