Dlaczego jednoczesne zapisy są niedozwolone w bazie danych SQLite?

79

Zajmuję się programowaniem baz danych za pomocą Java z SQLite.

Przekonałem się, że tylko jedno połączenie z bazą danych ma możliwość zapisu, podczas gdy wiele połączeń jednocześnie ma możliwość odczytu.

Dlaczego architektura SQLite została zaprojektowana w ten sposób? Tak długo, jak dwie rzeczy, które są zapisywane, nie są zapisywane w tym samym miejscu w bazie danych, dlaczego dwa zapisy nie mogą wystąpić jednocześnie?

Stalowy palec
źródło
5
Ponieważ SQLite został zaprojektowany jako „lite”. Niska pamięć i niskie przetwarzanie z wydajnością. Zastanów się, jak sprawić, by SQLite obsługiwał wiele zapisów do tego samego pliku. Obecny projekt jest łatwy do wdrożenia - cały plik jest zablokowany, a inni muszą czekać. Obsługa współbieżności zapisu na niższym poziomie szczegółowości wymaga blokowania wierszy / stron, które są uzyskiwane z RDMS. Jeśli wymaganie wymaga współbieżności zapisu, to SQLite nie jest kandydatem, a zamiast tego powinieneś spojrzeć na lekki RDBMS: en.wikipedia.org/wiki/…
Thomas Carlisle

Odpowiedzi:

157

Ponieważ „wielokrotne równoczesne zapisy” są o wiele, znacznie trudniejsze do osiągnięcia w silniku bazowym niż w przypadku pojedynczego zapisu i wielokrotnego odczytu. To wykracza poza parametry projektowe SQLite, a jego włączenie prawdopodobnie podważyłoby uroczo mały rozmiar i prostotę SQLite.

Wspieranie wysokiego stopnia współbieżności zapisu jest cechą charakterystyczną dużych silników baz danych, takich jak DB2, Oracle, SQL Server, MySQL, PostgreSQL, NonStop SQL i Sybase. Jest to jednak technicznie trudne do osiągnięcia, wymagając rozległej strategii kontroli i optymalizacji współbieżności, takiej jak blokowanie bazy danych, tabel i wierszy lub, w bardziej nowoczesnych implementacjach, kontroli współbieżności w wielu wersjach . Badanie tego problemu / wymagania jest obszerne i sięga dziesięcioleci .

SQLite ma zupełnie inną filozofię projektowania niż większość tych skoncentrowanych na serwerze DBMS, które obsługują wielu pisarzy. Został zaprojektowany, aby zapewnić moc SQL i modelu relacyjnego poszczególnym aplikacjom, a także być wbudowany w każdą aplikację. Ten cel wymaga znacznych kompromisów. Jednym z nich jest brak dodawania znacznej infrastruktury i kosztów ogólnych niezbędnych do obsługi wielu współbieżnych pisarzy.

Filozofię można streścić w instrukcji na odpowiedniej stronie SQLite :

SQLite nie konkuruje z bazami danych klient / serwer. SQLite konkuruje z fopen ().

Jonathan Eunice
źródło
41
+1. SQLite to wewnętrzna baza danych. Nie ma centralnego arbitra, jak w opartej na serwerze bazie danych. Pisarze musieliby bezpośrednio współpracować i ufać sobie. Pojedynczy złośliwy pisarz mógłby siać spustoszenie, po prostu nie współpracując.
Jörg W Mittag
12
Ponadto niektóre środowiska, w których działa SQLite, mogą nawet nie obsługiwać wielu procesów.
david25272
1
Przypuszczalnie złośliwe pismo może już siać spustoszenie przez brak współpracy. Nie mogą do tego użyć kodu SQLite, ale mogą mieć własny kod, który może być po prostu wywołaniem
unlink
12
W równoczesnych aplikacjach nie ma wiele pośrednich podstaw. Albo dostaniesz współbieżność, spójność i integralność danych w zasadzie w 100% przypadków, w tym w trudnych warunkach i przypadkach skrajnych, albo nie. Jeśli tego nie zrobisz, jest delikatny, wolny i podatny na awarie, a ludzie bardzo szybko przestają mu ufać. Ale rutynowe zrobienie tego jest diabelnie trudne. Nie ma tak wielu okoliczności, w których pisarze mogą, przy braku poparcia podstawowego wsparcia, samodzielnie koordynować przeplatane teksty.
Jonathan Eunice
8
@bdsl Bazy danych wszelkiego rodzaju muszą zakładać, że pisarze nie będą się dobrze zachowywać, więc nie stracą danych. Autorzy SQLite pozycjonują go jako konkurenta fopen(), więc weź pod uwagę cały włochaty charakter, jaki towarzyszy jednoczesnemu zapisywaniu do zwykłego pliku tekstowego.
Blrfl,
12

Ponieważ nie ma serwera, który mógłby stwierdzić, czy rzeczy mają być zapisane w tym samym miejscu, czy nie. Istnieją tylko dwa procesy próbujące zapisać do pliku.

Jak wskazano w komentarzu, jednoczesne zapisy mogą być również obsługiwane przez wewnętrzny wątek. Nie jestem pewien, jak dobrze to zadziała (też nie myślałem o tym zbyt wiele). Tak czy inaczej, dlaczego SQLite nie używa wątków: Dr Hipp uważa, że ​​wątki są złe.

Fakt, że DR Hipp uważa, że ​​wątki są złe, jest udokumentowany w FAQ SQLite .

Goyo
źródło
2
To wyjaśnia techniczny powód, dla którego jednoczesne zapisy są niedozwolone, ale nie uzasadnia decyzji projektowej.
Robert Harvey
3
Decyzja o zaprojektowaniu SQLite tak, aby obsługiwał tylko jeden zapis na raz.
Robert Harvey
7
@ Gooyo serwer nie jest wymagany do obsługi równoczesnych zapisów: ponieważ serwer bazy danych jest osobnym procesem, może istnieć osobny wątek wewnętrzny dla SQLite, który służy temu samemu celowi. Robert Harvey ma rację: zespół SQLite podjął decyzję projektową i nie ma to nic wspólnego ze zdolnością jednej biblioteki do obsługi równoczesnych zapisów (ponieważ teoretycznie może to zrobić).
1
Ta odpowiedź wydaje mi się w porządku. Do obsługi równoczesnych zapisów wydaje się, że trzeba mieć albo serwer, albo wielowątkową implementację sqlite. Ponieważ oba zostały wykluczone na podstawie innych decyzji projektowych, implementacja równoczesnych zapisów byłaby niezwykle trudna.
jpa
5
@jpa: SQLite potrafi zsynchronizować blokowanie między kilkoma procesami / wątkami bez „serwera”. „Serwer” nie jest wymagany - korzystanie z blokowania / synchronizacji / IPC / dostarczonego przez system operacyjny, co jest wystarczające, ale szybko się komplikuje. „Wątek wewnętrzny” wymieniony w poście nie ma sensu.
Mat.