sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Bagaimana cara membuka kunci basis data sehingga ini akan berfungsi?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Bagaimana cara membuka kunci basis data sehingga ini akan berfungsi?
Jawaban:
Di windows Anda dapat mencoba program ini http://www.nirsoft.net/utils/opened_files_view.html untuk mengetahui proses penanganan file db. Coba tutup program itu untuk membuka kunci basis data
Di Linux dan macOS Anda dapat melakukan sesuatu yang serupa, misalnya, jika file Anda terkunci pengembangan.db:
$ fuser development.db
Perintah ini akan menunjukkan proses apa yang mengunci file:
> development.db: 5430
Bunuh saja prosesnya ...
bunuh -9 5430
... Dan basis data Anda akan dibuka.
killharus baik-baik saja, tetapi Anda harus berhati-hati untuk membunuhnya dengan benar, dan kill -9mungkin salah dan / atau berlebihan. Jika prosesnya terhenti dan tidak akan mati, terkadang Anda memang membutuhkannya kill -9. Tetapi Anda tidak ingin pergi dan mematikan pekerjaan produksi utama hanya agar Anda dapat melaporkan bahwa basis data tidak lagi terkunci!
Saya menyebabkan sqlite db menjadi terkunci dengan menabrak aplikasi saat menulis. Inilah cara saya memperbaikinya:
echo ".dump" | sqlite old.db | sqlite new.db
Diambil dari: 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)
Halaman DatabaseIsLocked yang tercantum di bawah tidak lagi tersedia. Halaman Penguncian File dan Konkurensi menjelaskan perubahan terkait penguncian file yang diperkenalkan di v3 dan mungkin bermanfaat bagi pembaca di masa mendatang. https://www.sqlite.org/lockingv3.html
Halaman DatabaseIsLocked SQLiki wiki menawarkan penjelasan yang baik tentang pesan kesalahan ini. Ini menyatakan, sebagian, bahwa sumber pertengkaran adalah internal (untuk proses memancarkan kesalahan).
Apa yang tidak dijelaskan halaman ini adalah bagaimana SQLite memutuskan bahwa sesuatu dalam proses Anda memegang kunci dan kondisi apa yang dapat mengarah pada false positive.
Menghapus file -jurnal terdengar seperti ide yang buruk. Itu ada di sana untuk memungkinkan sqlite untuk memutar kembali database ke keadaan yang konsisten setelah crash. Jika Anda menghapusnya saat database dalam keadaan tidak konsisten, maka Anda pergi dengan database yang rusak. Mengutip halaman dari situs sqlite :
Jika crash atau kehilangan daya memang terjadi dan jurnal panas dibiarkan di disk, sangat penting bahwa file database asli dan jurnal panas tetap di disk dengan nama asli mereka sampai file database dibuka oleh proses SQLite lain dan digulung kembali . [...]
Kami menduga bahwa mode kegagalan umum untuk pemulihan SQLite terjadi seperti ini: Terjadi kegagalan daya. Setelah daya pulih, pengguna atau administrator sistem yang bermaksud baik mulai mencari-cari kerusakan pada disk. Mereka melihat file database mereka bernama "important.data". File ini mungkin tidak asing bagi mereka. Tetapi setelah crash, ada juga jurnal panas bernama "important.data-journal". Pengguna kemudian menghapus jurnal panas, berpikir bahwa mereka membantu membersihkan sistem. Kami tahu tidak ada cara untuk mencegah hal ini selain dari pendidikan pengguna.
Kembalikan seharusnya terjadi secara otomatis saat berikutnya database dibuka, tetapi itu akan gagal jika proses tidak dapat mengunci database. Seperti yang dikatakan orang lain, salah satu alasan yang memungkinkan untuk ini adalah bahwa proses lain saat ini terbuka. Kemungkinan lain adalah kunci NFS basi, jika database pada volume NFS. Dalam hal ini, solusinya adalah mengganti file database dengan salinan baru yang tidak terkunci pada server NFS (mv database.db original.db; cp original.db database.db). Perhatikan bahwa FAQ sqlite merekomendasikan kehati-hatian tentang akses bersamaan ke database pada volume NFS, karena implementasi penguncian file NFS yang bermasalah.
Saya tidak bisa menjelaskan mengapa menghapus file -jurnal akan membiarkan Anda mengunci basis data yang sebelumnya tidak bisa Anda lakukan. Apakah itu dapat direproduksi?
Ngomong-ngomong, keberadaan file -jurnal tidak selalu berarti bahwa ada crash atau ada perubahan yang harus dibatalkan. Sqlite memiliki beberapa mode jurnal yang berbeda, dan dalam mode PERSIST atau TRUNCATE ia meninggalkan file -jurnal pada tempatnya, dan mengubah konten untuk menunjukkan apakah ada transaksi parsial untuk memutar kembali.
Jika Anda ingin menghapus kesalahan "basis data dikunci" maka ikuti langkah-langkah ini:
Jika suatu proses memiliki kunci pada DB SQLite dan crash, DB tetap terkunci secara permanen. Itulah masalahnya. Bukannya beberapa proses lain memiliki kunci.
file db SQLite hanyalah file, jadi langkah pertama adalah memastikan itu bukan hanya-baca. Hal lain yang harus dilakukan adalah memastikan bahwa Anda tidak memiliki semacam penampil DB GUI SQLite dengan DB terbuka. Anda bisa membuka DB di shell lain, atau kode Anda mungkin memiliki DB terbuka. Biasanya Anda akan melihat ini jika utas yang berbeda, atau aplikasi seperti SQLite Database Browser memiliki DB terbuka untuk ditulis.
Saya punya masalah ini sekarang, menggunakan database SQLite pada server jauh, disimpan pada mount NFS. SQLite tidak dapat memperoleh kunci setelah sesi shell remote yang saya gunakan mengalami crash ketika database terbuka.
Resep untuk pemulihan yang disarankan di atas tidak bekerja untuk saya (termasuk ide untuk memindahkan terlebih dahulu dan kemudian menyalin database kembali). Tetapi setelah menyalinnya ke sistem non-NFS, database menjadi dapat digunakan dan bukan data yang tampaknya telah hilang.
Kunci saya disebabkan oleh sistem crash dan bukan oleh proses gantung. Untuk mengatasi ini saya cukup mengganti nama file kemudian menyalinnya kembali ke nama dan lokasi aslinya.
Menggunakan shell linux yang akan ...
mv mydata.db temp.db
cp temp.db mydata.db
Saya menambahkan " Pooling=true" ke string koneksi dan itu berhasil.
Saya menemukan dokumentasi berbagai negara mengunci SQLite sangat membantu. Michael, jika Anda dapat melakukan membaca tetapi tidak dapat melakukan menulis ke database, itu berarti bahwa suatu proses telah mendapatkan kunci RESERVED pada database Anda tetapi belum menjalankan penulisan. Jika Anda menggunakan SQLite3, ada kunci baru yang disebut PENDING di mana tidak ada lagi proses yang diizinkan untuk menyambungkan tetapi koneksi yang ada dapat tetap melakukan pembacaan, jadi jika ini masalahnya, Anda harus melihatnya.
Saya memiliki masalah seperti itu di dalam aplikasi, yang mengakses SQLite dari 2 koneksi - satu hanya-baca dan yang kedua untuk menulis dan membaca. Sepertinya koneksi read-only memblokir penulisan dari koneksi kedua. Akhirnya, ternyata diperlukan untuk menyelesaikan atau, setidaknya, mengatur ulang pernyataan yang disiapkan SEGERA setelah digunakan. Sampai pernyataan yang disiapkan dibuka, itu menyebabkan database diblokir untuk penulisan.
JANGAN LUPA PANGGILAN:
sqlite_reset(xxx);
atau
sqlite_finalize(xxx);
Beberapa fungsi, seperti INDEX'ing, dapat memakan waktu sangat lama - dan mengunci seluruh basis data saat dijalankan. Dalam hal seperti itu, bahkan mungkin tidak menggunakan file jurnal!
Jadi cara terbaik / satu-satunya untuk memeriksa apakah basis data Anda terkunci karena suatu proses AKTIF menulisnya (dan dengan demikian Anda harus membiarkannya sendiri sampai selesai operasinya) adalah dengan md5 (atau md5sum pada beberapa sistem) file dua kali . Jika Anda mendapatkan checksum yang berbeda, database sedang ditulis, dan Anda benar-benar BENAR-BENAR tidak ingin membunuh -9 proses itu karena Anda dapat dengan mudah berakhir dengan tabel / database yang korup jika Anda melakukannya.
Saya akan mengulangi, karena ini penting - solusinya adalah TIDAK menemukan program penguncian dan membunuhnya - itu untuk menemukan apakah database memiliki kunci tulis untuk alasan yang baik, dan pergi dari sana. Terkadang solusi yang tepat adalah hanya coffee break.
Satu-satunya cara untuk membuat situasi terkunci-tapi-tidak-sedang-ditulis-ke ini adalah jika program Anda berjalan BEGIN EXCLUSIVE, karena ingin melakukan beberapa perubahan tabel atau sesuatu, maka untuk alasan apa pun tidak pernah mengirim ENDsesudahnya, dan proses tidak pernah berakhir . Ketiga kondisi yang dipenuhi sangat tidak mungkin dalam kode yang ditulis dengan benar, dan dengan demikian 99 kali dari 100 ketika seseorang ingin membunuh -9 proses penguncian mereka, proses penguncian sebenarnya mengunci database Anda untuk alasan yang baik. Pemrogram biasanya tidak menambahkan BEGIN EXCLUSIVEkondisi kecuali mereka benar-benar perlu, karena mencegah konkurensi dan meningkatkan keluhan pengguna. SQLite sendiri hanya menambahkannya ketika benar-benar perlu (seperti saat pengindeksan).
Akhirnya, status 'terkunci' tidak ada DI DALAM file seperti yang telah dijawab beberapa jawaban - ia berada di kernel Sistem Operasi. Proses yang dijalankan BEGIN EXCLUSIVEtelah meminta dari OS kunci ditempatkan pada file. Bahkan jika proses eksklusif Anda macet, OS Anda akan dapat mengetahui apakah harus menjaga kunci file atau tidak !! Tidak mungkin berakhir dengan basis data yang terkunci tetapi tidak ada proses yang secara aktif menguncinya !! Ketika datang untuk melihat proses mana yang mengunci file, biasanya lebih baik menggunakan lsof daripada fuser (ini adalah demonstrasi yang bagus tentang mengapa: /unix/94316/fuser-vs-lsof- to-check-files-in-use ). Atau jika Anda memiliki DTrace (OSX), Anda dapat menggunakan iosnoop pada file.
Saya baru saja mengalami hal serupa pada saya - aplikasi web saya dapat membaca dari database, tetapi tidak dapat melakukan sisipan atau pembaruan. Reboot Apache memecahkan masalah setidaknya untuk sementara waktu.
Akan lebih baik, bagaimanapun, untuk dapat melacak penyebab dasarnya.
Tautan ini memecahkan masalah. : Ketika Sqlite memberikan: Kesalahan terkunci di basis data Memecahkan masalah saya mungkin bermanfaat bagi Anda.
Dan Anda dapat menggunakan mulai transaksi dan akhiri transaksi untuk tidak membuat basis data dikunci di masa mendatang.
Seharusnya menjadi masalah internal basis data ...
Bagi saya itu telah dimanifestasikan setelah mencoba menelusuri basis data dengan "SQLite manager" ...
Jadi, jika Anda tidak dapat menemukan proses lain terhubung ke basis data dan Anda tidak dapat memperbaikinya, coba saja solusi radikal ini:
rake db:migrate"Saya mengalami masalah yang sama pada Mac OS X 10.5.7 menjalankan skrip Python dari sesi terminal. Meskipun saya telah menghentikan skrip dan jendela terminal duduk di command prompt, itu akan memberikan kesalahan ini saat dijalankan berikutnya. Solusinya adalah dengan menutup jendela terminal dan kemudian membukanya lagi. Tidak masuk akal bagi saya, tetapi itu berhasil.
Saya memiliki masalah yang sama. Rupanya fungsi rollback tampaknya menimpa file db dengan jurnal yang sama dengan file db tetapi tanpa perubahan terbaru. Saya sudah menerapkan ini dalam kode saya di bawah ini dan sudah berfungsi dengan baik sejak saat itu, sedangkan sebelum kode saya hanya akan terjebak dalam loop karena database tetap terkunci.
Semoga ini membantu
##############
#### 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 )
Salah satu alasan umum untuk mendapatkan pengecualian ini adalah ketika Anda mencoba melakukan operasi tulis sambil tetap memegang sumber daya untuk operasi baca. Misalnya, jika Anda MEMILIH dari tabel, dan kemudian mencoba untuk MEMPERBARUI sesuatu yang telah Anda pilih tanpa menutup ResultSet Anda terlebih dahulu.
Saya mengalami "database terkunci" kesalahan dalam aplikasi multi-threaded juga, yang tampaknya menjadi kode hasil SQLITE_BUSY , dan saya menyelesaikannya dengan menetapkan sqlite3_busy_timeout ke sesuatu yang sesuai dengan panjang seperti 30000.
(Di samping catatan, betapa aneh bahwa pada pertanyaan berusia 7 tahun tidak ada yang tahu ini! SQLite benar-benar adalah proyek yang aneh dan menakjubkan ...)
Sebelum turun opsi reboot, ada baiknya untuk melihat apakah Anda dapat menemukan pengguna dari database sqlite.
Di Linux, seseorang dapat menggunakan fuseruntuk tujuan ini:
$ fuser database.db
$ fuser database.db-journal
Dalam kasus saya, saya mendapat respons berikut:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
Yang menunjukkan bahwa saya punya program Python lain dengan pid 3556 (manage.py) menggunakan database.
Sebuah pertanyaan lama, dengan banyak jawaban, inilah langkah-langkah yang saya ikuti baru-baru ini membaca jawaban di atas, tetapi dalam kasus saya masalahnya adalah karena berbagi sumber daya cifs. Kasus ini tidak dilaporkan sebelumnya, jadi semoga membantu seseorang.
Cobalah untuk memaksa mode kunci pada pembukaan koneksi dengan
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());Jika Anda menggunakan file db SQLite Anda di folder bersama NFS, periksa titik faq SQLite ini, dan tinjau opsi konfigurasi pemasangan Anda untuk memastikan Anda menghindari kunci, seperti dijelaskan di sini :
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
Saya mendapatkan kesalahan ini dalam skenario yang sedikit berbeda dari yang dijelaskan di sini.
Basis data SQLite bersandar pada sistem file NFS yang dibagikan oleh 3 server. Pada 2 server saya berhasil menjalankan query pada database, pada pemikiran ketiga saya mendapatkan pesan "database is locked".
Masalahnya dengan mesin ke-3 ini adalah tidak ada ruang tersisa /var. Setiap kali saya mencoba menjalankan kueri di database SQL APAPUN yang terletak di sistem file ini, saya menerima pesan "database is locked" dan juga kesalahan ini di atas log:
8 Agustus 10:33:38 server01 kernel: lockd: tidak dapat memantau 172.22.84.87
Dan yang ini juga:
8 Agustus 10:33:38 server01 rpc.statd [7430]: Gagal menyisipkan: menulis /var/lib/nfs/statd/sm/other.server.name.com: Tidak ada ruang tersisa di perangkat 8 Agustus 10:33: 38 server01 rpc.statd [7430]: STAT_FAIL ke server01 untuk SM_MON dari 172.22.84.87
Setelah situasi ruang ditangani semuanya kembali normal.
Jika Anda mencoba membuka kunci basis data Chrome untuk melihatnya dengan SQLite , maka matikan saja Chrome.
Windows
%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
Dari komentar Anda sebelumnya, Anda mengatakan file jurnal ada.
Ini bisa berarti bahwa Anda telah membuka dan (EKSKLUSIF?) Transaksi dan belum melakukan data. Apakah program Anda atau proses lain meninggalkan -jurnal?
Restart proses sqlite akan melihat file jurnal dan membersihkan setiap tindakan yang tidak berkomitmen dan menghapus file -journal
Seperti dikatakan Seun Osewa, kadang-kadang proses zombie akan duduk di terminal dengan kunci yang diperoleh, bahkan jika Anda tidak berpikir itu mungkin. Script Anda berjalan, macet, dan Anda kembali ke prompt, tetapi ada proses zombie yang muncul di suatu tempat oleh panggilan perpustakaan, dan proses itu memiliki kunci.
Menutup terminal tempat Anda berada (pada OSX) mungkin berhasil. Mulai ulang akan berhasil. Anda bisa mencari proses "python" (misalnya) yang tidak melakukan apa-apa, dan membunuh mereka.
Anda dapat mencoba ini: .timeout 100untuk mengatur batas waktu. Saya tidak tahu apa yang terjadi di baris perintah tetapi di C # .Net ketika saya melakukan ini: "UPDATE table-name SET column-name = value;"Saya mendapatkan Basis Data terkunci tetapi ini "UPDATE table-name SET column-name = value"berjalan dengan baik.
Sepertinya ketika Anda menambahkan;, sqlite akan mencari perintah lebih lanjut.