SQLite3, aynı DB'den okuma / yazma işlemlerini birden çok işlemle eşzamanlı erişimi güvenli bir şekilde ele alıyor mu? Bunun için herhangi bir platform istisnası var mı?
SQLite3, aynı DB'den okuma / yazma işlemlerini birden çok işlemle eşzamanlı erişimi güvenli bir şekilde ele alıyor mu? Bunun için herhangi bir platform istisnası var mı?
Yanıtlar:
Bu eşzamanlı erişimlerin çoğu okunursa (örn. SELECT), SQLite bunları çok iyi işleyebilir. Ancak aynı anda yazmaya başlarsanız, kilit çekişme sorun haline gelebilir. SQLite motorunun kendisi son derece hızlı olduğundan ve çekişmeyi en aza indirmek için birçok akıllı optimizasyona sahip olduğundan, birçok şey dosya sisteminizin ne kadar hızlı olduğuna bağlı olacaktır. Özellikle SQLite 3.
Çoğu masaüstü / dizüstü bilgisayar / tablet / telefon uygulaması için, yeterli eşzamanlılık olmadığı için SQLite yeterince hızlıdır. (Firefox, yer imleri, geçmiş vb. İçin SQLite'yi yaygın olarak kullanır)
Sunucu uygulamaları için, bir süre önce birisi, günde 100 bin sayfadan daha az bir şeyin tipik senaryolarda (örn. Bloglar, forumlar) bir SQLite veritabanı tarafından mükemmel bir şekilde ele alınabileceğini söyledi ve bunun aksine bir kanıt görmedim. Aslında, modern diskler ve işlemcilerle, web sitelerinin ve web hizmetlerinin% 95'i SQLite ile iyi çalışır.
Gerçekten hızlı okuma / yazma erişimi istiyorsanız, bir bellek içi SQLite veritabanı kullanın . RAM, diskten daha hızlı birkaç kat daha büyüktür.
Evet, SQLite eşzamanlılığı iyi işler, ancak performans açısından en iyisi değildir. Söyleyebileceğimden, bunun istisnası yok. Ayrıntılar SQLite sitesinde bulunmaktadır: https://www.sqlite.org/lockingv3.html
Bu deyim ilgi çekicidir: "Çağrı modülü, değişikliklerin bir anda gerçekleşmesini, tüm değişikliklerin gerçekleşmesini veya hiçbirinin yapılmamasını, iki veya daha fazla işlemin veritabanına aynı anda uyumsuz yollarla erişmeye çalışmadığını garanti eder."
Evet öyle. Neden olduğunu anlayalım
SQLite'taki tek bir işlemdeki tüm değişiklikler ya tamamen gerçekleşir ya da hiç gerçekleşmez
Bu tür ACID desteği ve eşzamanlı okuma / yazma işlemleri 2 yolla sağlanır - günlük kaydı adı verilen ( eski yöntem olarak adlandıralım ) veya yazma öncesi günlük kaydı (" yeni yöntem " olarak adlandırılır)
Bu modda SQLite, DATABASE-LEVEL kilitleme kullanır . Bunu anlamak çok önemli.
Bu, bir şeyi okumak / yazmak gerektiğinde, ilk önce ENTIRE veritabanı dosyasında bir kilit elde ettiği anlamına gelir . Birden fazla okuyucu birlikte var olabilir ve paralel olarak bir şey okuyabilir
Yazma sırasında özel bir kilidin alındığından ve başka hiçbir işlemin aynı anda okuma / yazma yapmadığından ve yazmaların güvenli olduğundan emin olur.
Bu nedenle burada onlar SQLite uygular söylüyorsun serilestirilebilir işlemler
Her seferinde tüm bir veritabanını kilitlemesi gerektiğinden ve herkes yazma işleminin eşzamanlılıktan muzdarip olduğunu ve bu tür eşzamanlı yazma / okumaların oldukça düşük performans gösterdiğinden
Bir şey veritabanı dosyasına yazılmadan önce SQLite öncelikle değiştirilecek parçayı geçici bir dosyaya kaydederdi. Veritabanı dosyasına yazmanın ortasında bir şey çökerse, bu geçici dosyayı alır ve değişiklikleri geri alır
Bu durumda, tüm yazma işlemleri geçici bir dosyaya eklenir ( önceden yazma günlüğü ) ve bu dosya periyodik olarak orijinal veritabanıyla birleştirilir. SQLite bir şey ararken öncelikle bu geçici dosyayı kontrol eder ve hiçbir şey bulunmazsa ana veritabanı dosyasıyla devam edin.
Sonuç olarak, okuyucular yazarlarla rekabet etmez ve performans Eski Yol'a kıyasla çok daha iyidir.
SQlite büyük ölçüde altta yatan dosya sistemi kilitleme işlevine bağlıdır, bu yüzden dikkatli kullanılmalıdır, daha fazla ayrıntı burada
Ayrıca , özellikle günlüklü modda veritabanında kilitli bir hatayla karşılaşma olasılığınız olduğundan, uygulamanızın bu hata göz önünde bulundurularak tasarlanması gerekir
Kimse WAL (İleriye Günlüğe Yaz) modundan bahsetmemiş gibi görünüyor. İşlemlerin düzgün bir şekilde organize edildiğinden ve WAL modu açıkken, bir güncelleme devam ederken insanlar bir şeyler okurken veritabanını kilitli tutmaya gerek yoktur.
Tek sorun, bir noktada WAL'ın ana veritabanına yeniden dahil edilmesi gerektiğidir ve veritabanına son bağlantı kapatıldığında bunu yapar. Çok yoğun bir siteyle, tüm bağlantıların yakın olması birkaç saniye alabilir, ancak günde 100.000 sonuç bir sorun olmamalıdır.
database is locked
hatadan sonra yazar tarafından yükseltileceğini belirtmek gerekir
2019'da henüz yayınlanmamış ancak ayrı dallarda bulunan iki yeni eşzamanlı yazma seçeneği var.
Bu günlük kipinin normal "wal" kipine göre avantajı, yazarların diğeri kontrol işaretli iken bir wal dosyasına yazmaya devam edebilmeleridir.
CONCURRENT'I BAŞLAT - ayrıntılı dokümana bağlantı
BEGIN CONCURRENT geliştirmesi, veritabanı "wal" veya "wal2" modundaysa, sistem hala COMMIT komutlarını serileştirse de, birden çok yazarın aynı anda yazma işlemlerini işlemesine izin verir.
"BAŞLANGIÇ BAŞLAT" ile bir yazma işlemi açıldığında, aslında bir COMMIT yürütülene kadar veritabanının kilitlenmesi ertelenir. Bu, BEGIN CONCURRENT ile başlatılan herhangi bir sayıda işlemin aynı anda devam edebileceği anlamına gelir. Sistem, çakışan eşzamanlı işlemlerin yapılmasını önlemek için iyimser sayfa düzeyinde kilitleme kullanır.
Birlikte, başlangıç -eşzamanlı-wal2'de veya her biri ayrı bir kendi dalında bulunurlar .
begin concurrent
şeyleri itiyorlardı.
SQLite, veritabanı düzeyinde bir okuyucu-yazar kilidine sahiptir . Birden fazla bağlantı (muhtemelen farklı işlemlerin sahip olduğu) aynı veritabanındaki verileri aynı anda okuyabilir, ancak veritabanına yalnızca bir tanesi yazabilir.
SQLite sınırsız sayıda eşzamanlı okuyucuyu destekler, ancak herhangi bir anda sadece bir yazara izin verir. Birçok durumda, bu bir sorun değildir. Yazar sırası yükseldi. Her uygulama veritabanını hızlı bir şekilde çalışır ve devam eder ve hiçbir kilit birkaç düzine milisaniyeden fazla sürmez. Ancak daha fazla eşzamanlılık gerektiren bazı uygulamalar vardır ve bu uygulamaların farklı bir çözüm araması gerekebilir. - SQLite @ SQLite.org İçin Uygun Kullanım Alanları
Okuyucu-yazar kilidi, bağımsız işlem işlemeyi mümkün kılar ve veritabanı düzeyinde özel ve paylaşılan kilitler kullanılarak uygulanır.
Bir bağlantı bir veritabanında yazma işlemi gerçekleştirmeden önce özel bir kilit alınmalıdır. Özel kilit elde edildikten sonra, kilit tekrar açılana kadar diğer bağlantılardan hem okuma hem de yazma işlemleri engellenir.
SQLite, maksimum eşzamanlılık sağlamak için yazma işlemi sırasında veritabanını olabildiğince geç kilitlemeye yardımcı olan bir kilit tablosuna sahiptir.
İlk durum KİLİTLENMEDİ ve bu durumda bağlantı henüz veritabanına erişmedi. Bir işlem bir veritabanına bağlandığında ve hatta BEGIN ile bir işlem başlatıldığında, bağlantı hala KİLİT AÇIK durumundadır.
UNLOCKED durumundan sonra, bir sonraki durum SHARED durumudur. Veritabanından veri okuyabilmek (yazamayabilmek) için, bağlantının önce bir PAYLAŞILAN kilit alarak SHARED durumuna girmesi gerekir. Birden çok bağlantı aynı anda PAYLAŞILAN kilitleri elde edip koruyabilir, böylece birden çok bağlantı aynı veritabanındaki verileri aynı anda okuyabilir. Ancak, yalnızca bir PAYLAŞILAN kilit bile yayınlanmadığı sürece, hiçbir bağlantı veritabanına yazma işlemini başarıyla tamamlayamaz.
Bir bağlantı veritabanına yazmak istiyorsa, ilk olarak bir REZERV kilit almalıdır.
Aynı anda yalnızca tek bir REZERV kilit etkin olabilir, ancak birden fazla PAYLAŞILAN kilit tek bir REZERV kilit ile birlikte bulunabilir. REZERV EDİLEN, REZERVED bir kilit varken yeni PAYLAŞILAN kilitlerin edinilebileceğinden PENDING'den farklıdır. - SQLite Sürüm 3'te Dosya Kilitleme ve Eşzamanlılık @ SQLite.org
Bir bağlantı bir REZERV kilit aldığında, veritabanı değişiklik işlemlerini işlemeye başlayabilir, ancak bu değişiklikler gerçekte diske yazılmak yerine yalnızca arabellekte yapılabilir. Okuma içeriğinde yapılan değişiklikler bellek arabelleğine kaydedilir. Bir bağlantı bir değişiklik (veya işlem) göndermek istediğinde, SAKLIDIR kilidini ÖZEL bir kilide yükseltmek gerekir. Kilidi almak için önce kilidi bir BEKLEME kilidine kaldırmanız gerekir.
BEKLEME kilidi, kilidi tutan işlemin mümkün olan en kısa sürede veritabanına yazmak istediğini ve ÖZEL bir kilit alabilmesi için tüm mevcut SHARED kilitlerinin temizlenmesini beklediği anlamına gelir. Beklemede bir kilit etkinse, veritabanına yeni PAYLAŞILAN kilitlerin girilmesine izin verilmez, ancak mevcut PAYLAŞILAN kilitlerin devam etmesine izin verilir.
Veritabanı dosyasına yazmak için özel bir kilit gerekir. Dosyada yalnızca bir EXCLUSIVE kilidine izin verilir ve EXCLUSIVE kilidiyle başka hiçbir kilidin bir arada bulunmasına izin verilmez. Eşzamanlılığı en üst düzeye çıkarmak için SQLite, ÖZEL kilitlerin tutulduğu süreyi en aza indirmeye çalışır. - SQLite Sürüm 3'te Dosya Kilitleme ve Eşzamanlılık @ SQLite.org
SQLite'nin aynı DB'ye yazdığı birden çok işlemle eşzamanlı erişimi güvenli bir şekilde işlediğini söyleyebilirsiniz, çünkü bunu desteklemez! Yeniden yazma sınırlamasına ulaştığında SQLITE_BUSY
ya SQLITE_LOCKED
da ikinci yazar için alacaksınız .
Bu iş parçacığı eski ama sqlite üzerinde yapılan testlerimin sonucunu paylaşmak için iyi olacağını düşünüyorum: I HARİKA kilit ve zaman aşımı ayarlanmış işlem içinde deyimleri SELECT ve UPDATE sql komutları yürütme 2 python programı (farklı işlemler aynı program) koştu Kilit almak için 10 saniye ve sonuç sinir bozucu oldu. Her örnek 10000 adım döngüsünde yaptı:
Sqlite işlem sırasında özel kilit vermiş olsa bile, gerçekten yürütülen döngülerin toplam sayısı 20 000'e eşit değil, daha azdı (tek bir sayaç üzerindeki toplam yineleme sayısı her iki işlem için sayıldı). Python programı neredeyse tek bir istisna atmadı (20 yürütme için seçim sırasında sadece bir kez). test anındaki sqlite revizyonu 3.6.20 ve python v3.3 CentOS 6.5 idi. Benim görüşüme göre, bu tür bir iş için daha güvenilir bir ürün bulmak ya da yazarı sqlite ile tek benzersiz işlem / iş parçacığıyla sınırlamak daha iyidir.
with con
yeterli olduğuna inanmanıza neden olmasına rağmen .