Apakah SQLite3 aman menangani akses bersamaan dengan beberapa proses membaca / menulis dari DB yang sama? Apakah ada pengecualian platform untuk itu?
Apakah SQLite3 aman menangani akses bersamaan dengan beberapa proses membaca / menulis dari DB yang sama? Apakah ada pengecualian platform untuk itu?
Jawaban:
Jika sebagian besar akses bersamaan dibaca (misalnya SELECT), SQLite dapat menanganinya dengan sangat baik. Tetapi jika Anda mulai menulis secara bersamaan, pertikaian kunci bisa menjadi masalah. Banyak yang kemudian akan bergantung pada seberapa cepat filesystem Anda, karena mesin SQLite itu sendiri sangat cepat dan memiliki banyak optimasi pintar untuk meminimalkan pertikaian. Terutama SQLite 3.
Untuk sebagian besar aplikasi desktop / laptop / tablet / telepon, SQLite cukup cepat karena tidak ada cukup konkurensi. (Firefox menggunakan SQLite secara ekstensif untuk bookmark, riwayat, dll.)
Untuk aplikasi server, seseorang beberapa waktu lalu mengatakan bahwa tampilan halaman kurang dari 100 ribu sehari dapat ditangani dengan sempurna oleh database SQLite dalam skenario tipikal (misalnya blog, forum), dan saya belum melihat bukti yang bertentangan. Bahkan, dengan disk dan prosesor modern, 95% situs web dan layanan web akan bekerja dengan baik dengan SQLite.
Jika Anda ingin akses baca / tulis yang sangat cepat, gunakan database SQLite di dalam memori . RAM beberapa kali lipat lebih cepat daripada disk.
Ya, SQLite menangani konkurensi dengan baik, tetapi itu bukan yang terbaik dari sudut kinerja. Dari apa yang saya tahu, tidak ada pengecualian untuk itu. Detailnya ada di situs SQLite: https://www.sqlite.org/lockingv3.html
Pernyataan ini menarik: "Modul pager memastikan perubahan terjadi sekaligus, bahwa semua perubahan terjadi atau tidak ada yang dilakukan, bahwa dua atau lebih proses tidak mencoba mengakses database dengan cara yang tidak kompatibel pada saat yang sama"
Ya itu. Mari kita cari tahu alasannya
Semua perubahan dalam satu transaksi dalam SQLite terjadi sepenuhnya atau tidak sama sekali
Dukungan ACID dan baca / tulis bersamaan disediakan dalam 2 cara - menggunakan apa yang disebut penjurnalan (sebut saja " cara lama ") atau pencatatan selanjutnya ( tuliskan " cara baru ")
Dalam mode ini SQLite menggunakan penguncian DATABASE-LEVEL . Ini adalah poin penting untuk dipahami.
Itu berarti setiap kali perlu membaca / menulis sesuatu, pertama-tama ia akan mendapatkan kunci pada file database SELURUH . Banyak pembaca dapat hidup berdampingan dan membaca sesuatu secara paralel
Selama menulis itu memastikan kunci eksklusif diperoleh dan tidak ada proses lain membaca / menulis secara bersamaan dan karenanya menulis aman.
Inilah sebabnya mengapa di sini mereka mengatakan bahwa SQlite mengimplementasikan transaksi berseri
Karena perlu mengunci seluruh basis data setiap kali dan semua orang menunggu proses penanganan penulisan konkurensi menderita dan penulisan / pembacaan bersamaan tersebut memiliki kinerja yang cukup rendah
Sebelum menulis sesuatu ke file database, SQLite terlebih dahulu akan menyimpan potongan untuk diubah dalam file sementara. Jika sesuatu crash di tengah penulisan ke dalam file database itu akan mengambil file sementara ini dan mengembalikan perubahan darinya
Dalam hal ini semua penulisan ditambahkan ke file sementara ( write-ahead log ) dan file ini secara berkala digabungkan dengan database asli. Ketika SQLite sedang mencari sesuatu, pertama-tama ia akan memeriksa file sementara ini dan jika tidak ada yang ditemukan lanjutkan dengan file database utama.
Akibatnya, pembaca tidak bersaing dengan penulis dan kinerjanya jauh lebih baik dibandingkan dengan Cara Lama.
SQlite sangat tergantung pada fungsi penguncian sistem file yang mendasarinya sehingga harus digunakan dengan hati-hati, lebih detail di sini
Anda juga kemungkinan akan mengalami kesalahan terkunci di dalam basis data , terutama dalam mode penjurnalan sehingga aplikasi Anda harus dirancang dengan mengingat kesalahan ini.
Sepertinya tidak ada yang menyebutkan mode WAL (Write Ahead Log). Pastikan transaksi diatur dengan benar dan dengan mode WAL diaktifkan, tidak perlu untuk menjaga basis data tetap terkunci sementara orang-orang membaca hal-hal sementara pembaruan sedang berlangsung.
Satu-satunya masalah adalah bahwa pada beberapa titik WAL perlu dimasukkan kembali ke dalam database utama, dan hal ini terjadi ketika koneksi terakhir ke database ditutup. Dengan situs yang sangat sibuk, Anda mungkin perlu beberapa detik untuk menutup semua koneksi, tetapi 100 ribu hit per hari seharusnya tidak menjadi masalah.
database is lockedkesalahan itu akan dinaikkan oleh penulis
Pada tahun 2019, ada dua opsi penulisan konkuren baru yang belum dirilis tetapi tersedia di cabang terpisah.
Keuntungan dari mode jurnal ini daripada mode "wal" biasa adalah bahwa penulis dapat terus menulis ke satu file wal sementara yang lain diperiksa dengan cermat.
BEGIN CONCURRENT - tautan ke dokumen terperinci
Peningkatan BEGIN CONCURRENT memungkinkan banyak penulis untuk memproses transaksi penulisan secara simultan jika database berada dalam mode "wal" atau "wal2", meskipun sistem masih membuat serial perintah COMMIT.
Ketika transaksi menulis dibuka dengan "BEGIN CONCURRENT", sebenarnya mengunci basis data ditangguhkan sampai KOMIT dijalankan. Ini berarti bahwa sejumlah transaksi yang dimulai dengan BEGIN CONCURRENT dapat dilanjutkan secara bersamaan. Sistem ini menggunakan penguncian tingkat-halaman yang optimis untuk mencegah komitmen transaksi bersamaan yang bertentangan.
Bersama-sama mereka hadir dalam wal-concurrent-wal2 atau masing-masing dalam cabang yang terpisah .
begin concurrentbarang - barang itu.
SQLite memiliki kunci pembaca-penulis pada tingkat basis data. Banyak koneksi (mungkin dimiliki oleh proses yang berbeda) dapat membaca data dari database yang sama pada saat yang sama, tetapi hanya satu yang dapat menulis ke database.
SQLite mendukung jumlah pembaca simultan yang tidak terbatas, tetapi hanya akan memungkinkan satu penulis setiap saat. Untuk banyak situasi, ini bukan masalah. Penulis mengantri. Setiap aplikasi melakukan pekerjaan databasenya dengan cepat dan bergerak, dan tidak ada kunci yang bertahan lebih dari beberapa lusin milidetik. Tetapi ada beberapa aplikasi yang membutuhkan konkurensi lebih banyak, dan aplikasi tersebut mungkin perlu mencari solusi yang berbeda. - Penggunaan Yang Tepat Untuk SQLite @ SQLite.org
Kunci pembaca-penulis memungkinkan pemrosesan transaksi independen dan diimplementasikan menggunakan kunci eksklusif dan bersama di tingkat basis data.
Kunci eksklusif harus diperoleh sebelum koneksi melakukan operasi penulisan pada database. Setelah kunci eksklusif diperoleh, operasi baca dan tulis dari koneksi lain diblokir hingga kunci dilepaskan lagi.
SQLite memiliki tabel kunci yang membantu mengunci database selambat mungkin selama operasi penulisan untuk memastikan konkurensi maksimum.
Keadaan awal UNLOCKED, dan dalam kondisi ini, koneksi belum mengakses database. Ketika suatu proses terhubung ke database dan bahkan transaksi telah dimulai dengan BEGIN, koneksi masih dalam keadaan UNLOCKED.
Setelah negara UNLOCKED, negara berikutnya adalah negara SHARED. Agar dapat membaca (tidak menulis) data dari basis data, koneksi harus terlebih dahulu memasuki kondisi SHARED, dengan mendapatkan kunci SHARED. Beberapa koneksi dapat memperoleh dan memelihara kunci SHARED pada saat yang sama, sehingga beberapa koneksi dapat membaca data dari database yang sama pada saat yang sama. Tetapi selama hanya satu kunci SHARED yang tidak dirilis, tidak ada koneksi yang berhasil menyelesaikan penulisan ke database.
Jika koneksi ingin menulis ke database, pertama-tama harus mendapatkan kunci RESERVED.
Hanya satu kunci RESERVED yang dapat aktif pada satu waktu, meskipun beberapa kunci SHARED dapat hidup berdampingan dengan satu kunci RESERVED. RESERVED berbeda dari PENDING di mana kunci SHARED baru dapat diperoleh saat ada kunci RESERVED. - Penguncian File Dan Konkurensi Dalam SQLite Versi 3 @ SQLite.org
Setelah koneksi memperoleh kunci RESERVED, itu dapat mulai memproses operasi modifikasi database, meskipun modifikasi ini hanya dapat dilakukan dalam buffer, daripada benar-benar ditulis ke disk. Modifikasi yang dilakukan pada konten pembacaan disimpan dalam buffer memori. Ketika koneksi ingin mengirimkan modifikasi (atau transaksi), perlu untuk memperbarui kunci RESERVED ke kunci EKSKLUSIF. Untuk mendapatkan kunci, Anda harus terlebih dahulu mengangkat kunci ke kunci PENDING.
Kunci PENDING berarti bahwa proses menahan kunci ingin menulis ke database sesegera mungkin dan hanya menunggu semua kunci SHARED saat ini untuk menghapus sehingga bisa mendapatkan kunci EKSKLUSIF. Tidak ada kunci SHARED baru diizinkan terhadap database jika kunci PENDING aktif, meskipun kunci SHARED yang ada diizinkan untuk melanjutkan.
Kunci EKSKLUSIF diperlukan untuk menulis ke file database. Hanya satu kunci EKSKLUSIF yang diizinkan pada file dan tidak ada kunci lain dalam bentuk apa pun yang diizinkan untuk hidup berdampingan dengan kunci EKSKLUSIF. Untuk memaksimalkan konkurensi, SQLite berfungsi untuk meminimalkan jumlah waktu yang dimiliki kunci EKSKLUSIF. - Penguncian File Dan Konkurensi Dalam SQLite Versi 3 @ SQLite.org
Jadi Anda bisa mengatakan SQLite dengan aman menangani akses bersamaan dengan beberapa proses menulis ke DB yang sama hanya karena tidak mendukungnya! Anda akan mendapatkan SQLITE_BUSYatau SQLITE_LOCKEDuntuk penulis kedua saat mencapai batasan coba lagi.
Utas ini sudah lama tetapi saya pikir akan lebih baik untuk berbagi hasil pengujian saya yang dilakukan di sqlite: saya menjalankan 2 contoh program python (proses yang berbeda dengan program yang sama) mengeksekusi pernyataan SELECT dan UPDATE perintah sql dalam transaksi dengan kunci EKSKLUSIF dan batas waktu disetel ke 10 detik untuk mendapatkan kunci, dan hasilnya membuat frustrasi. Setiap contoh dilakukan dalam 10.000 langkah loop:
Bahkan jika sqlite memberikan kunci eksklusif pada transaksi, jumlah total siklus yang benar-benar dieksekusi tidak sama dengan 20 000 tetapi lebih sedikit (jumlah total iterasi atas penghitung tunggal dihitung untuk kedua proses). Program python hampir tidak membuang satu pun pengecualian (hanya sekali selama pilih untuk 20 eksekusi). revisi sqlite pada saat pengujian adalah 3.6.20 dan python v3.3 CentOS 6.5. Menurut pendapat saya, lebih baik untuk menemukan produk yang lebih dapat diandalkan untuk jenis pekerjaan ini atau membatasi menulis ke sqlite untuk satu proses / utas unik.
with consudah cukup.