2012-07-31 7 views
11

Mam aplikację, która używa SQLite (wersja 3.7.2) do przechowywania danych. Mam połączenie SQLite współużytkowane przez wiele wątków, które zapisuje i czyta z tego samego SQLite db. SQLite jest kompilowany przy użyciu DSQLITE_THREADSAFE = 1, co oznacza, że ​​SQLite jest w trybie Serialized.SQLite: Udostępnianie połączeń między wątkami do odczytu i zapisu

Cytując SQLite docs

szeregowane: W trybie odcinkach, SQLite może być bezpiecznie stosowany przez wielu wątki bez ograniczeń.

Wręcz przeciwnie wpis SQLite Wiki mówi

Nie używaj tego samego połączenia z bazą danych w tym samym czasie w ponad jeden wątek

Próbowałem z przykładowej aplikacji tego ikra setki wątków i udostępniają uchwyt SQLite do odczytu, który działa poprawnie.

Czy wpis wiki SQLite jest nieaktualny, czy SQLite może nie być w stanie obsłużyć operacji odczytu i zapisu z różnych wątków w tym samym czasie przy użyciu tego samego połączenia?

Odpowiedz

7

EDIT

DSQLITE_THREADSAFE = 2: Tryb wielonitkowa Określenie "Multi-nici" jest nieco zmieszany w SQLite. Wydaje się, że w trybie wielowątkowym nie można współużytkować połączenia z innymi wątkami, ponieważ samo połączenie nie będzie używać muteksów, aby jeden wątek nie modyfikował połączenia, gdy inny wątek go używa.

DSQLITE_THREADSAFE = 1: Tryb odcinkach Jednak w serializowanym trybie, to zablokuje plik danych i użyje muteksy kontrolować dostęp do udostępnionego połączenia.

Od dokumentów: ... gdy SQLite jest kompilowany z SQLITE_THREADSAFE = 1, biblioteka SQLite sama przekształci się w dostęp do połączeń z bazami danych i przygotowanych instrukcji, dzięki czemu aplikacja będzie mogła korzystać z tego samego połączenia z bazą danych lub z tego samego przygotowanego wyciągu w różnych wątkach w tym samym czasie.

Więc, gdy ma do czynienia z połączeniami, tryb odcinkach jest wątku bezpieczny ale wielonitkowa tryb nie jest, choć nadal można mieć wiele połączeń do tej samej bazy danych.

Źródło: http://www.sqlite.org/c3ref/c_config_getmalloc.html#sqliteconfigmultithread

Pozdrawiam!

+2

Przeczytałem o tym, ale zastanawiałem się, czy wiki jest nieaktualne, czy też połączenie SQLite obsługuje teraz "reads" i "write" z tego samego połączenia z wielu wątków? – omggs

+0

@omggs masz rację. Warunki są trochę mylące w dokumentach SQLite. Dla mnie * multi-thread * i * serialized * były takie same, ale nie są. Używam połączeń szeregowych, ale nie dzielę ich między wątkami ... a teraz dowiedziałem się, że można się bezpiecznie dzielić :) – devundef

+1

Dzięki za potwierdzenie! Wiki SQLite jest rzeczywiście nieaktualne !!! – omggs

0

To zły pomysł, aby dzielić jedno połączenie między więcej niż jednego wątku, gdy masz DSQLITE_THREADSAFE = 0

Wyobraź sobie gwintu 1 wykonuje ten kod:

1. connection.setAutoCommit(false); 
2. statement.executeUpdate(sql); 
3. connection.commit(); 

i swój wątek 2 jest wykonywany ten kod w tym samym czasie:

1. connection.setAutoCommit(true); 

Co się stanie, jeśli instrukcja 1 z THREAD 2 zostanie wykonana dokładnie PRZED instrukcją 3 GWINTU 1? Prawdopodobnie uzyskasz wyjątek SQLException z komunikatem "baza danych w trybie automatycznego zatwierdzania" (ponieważ metody automatycznego zatwierdzania są wykonywane na tym samym obiekcie Connection).

Oznacza to trzeba zsynchronizować jego użytkowania ruda kod DSQLITE_THREADSAFE = 1

Korzystanie z puli połączeń byłoby też najlepiej, jeśli masz zamiar aktywnie rozwija Multithread kod, z którego można uzyskać lepszą wydajność, gdy zdecydujesz się wybrać inny DBMS.