2012-06-15 13 views
9

Próbuję określić, czy mój dostęp do bazy danych sqlite jest bezpieczny dla wątków w systemie iOS. Piszę aplikację inną niż App Store (lub prawdopodobnie demon uruchamiania), więc zatwierdzenie Apple nie stanowi problemu. Wspomniana baza danych to wbudowany sms.db, więc z pewnością system operacyjny również uzyskuje dostęp do tej bazy danych do odczytu i zapisu. Chcę tylko móc to bezpiecznie przeczytać.Interprocess SQLite Bezpieczeństwo wątków (w systemie iOS)

Czytałem this about reading from multiple processes with sqlite:

wiele procesów może mieć taką samą bazę otwarty w tym samym czasie. Wiele procesów może wykonywać SELECT w tym samym czasie. Jednak tylko jeden proces może wprowadzać zmiany w bazie danych w dowolnym momencie w czasie .

Rozumiem, że bezpieczeństwo wątków może zostać skompilowane z sqlite, a do testowania można użyć testu sqlite3_threadsafe(). Bieganie to na iOS 5.0.1

int safe = sqlite3_threadsafe(); 

daje wynik 2. According to this, że środki blokujące mutex jest dostępny. Ale to niekoniecznie oznacza, że ​​jest w użyciu.

Nie jestem całkiem pewien, czy bezpieczeństwo wątków jest dynamicznie włączane w odniesieniu do jednego połączenia, bazy danych czy globalnej.

I have also read this. Wygląda na to, że można użyć sqlite3_config(), aby umożliwić bezpieczne wielowątkowość, ale oczywiście nie mam żadnej kontroli, ani widoczności, w jaki sposób system operacyjny mógł użyć tego połączenia (czy ja?). Gdybym miał wykonać to wezwanie ponownie w mojej aplikacji, czy pozwoliłoby to na bezpieczne odczytanie bazy danych, czy też spowodowałoby jedynie dekonflikację równoczesnego dostępu dla wielu wątków w mojej aplikacji, która używała tego samego handle bazy danych sqlite3?

W każdym razie, moje pytanie brzmi ...

mogę spokojnie czytać tę bazę danych, która jest również uzyskać przez iOS, a jeśli tak, to w jaki sposób?

Odpowiedz

10

Nigdy nie używałem SQLite, ale spędziłem przyzwoitą ilość czasu czytając jego dokumenty, ponieważ planuję używać go w przyszłości (a dokumenty są interesujące). Powiedziałbym, że bezpieczeństwo wątków jest niezależne od tego, czy wiele procesów może jednocześnie uzyskać dostęp do tego samego pliku bazy danych. SQLite, niezależnie od tego, w jakim trybie wątkowania jest, będzie lock the database file, tak że wiele procesów może od razu odczytać z bazy danych, ale tylko jeden może pisać.

Thread safety wpływa tylko na to, jak proces może korzystać z SQLite. Bez żadnego zabezpieczenia wątków można wywoływać funkcje SQLite tylko z jednego wątku. Jednak przed zapisaniem powinien on, na przykład, wybrać blokadę EXCLUSIVE, aby inne procesy nie mogły uszkodzić pliku bazy danych. Bezpieczeństwo wątków chroni dane w pamięci twojego procesu przed uszkodzeniem, jeśli używasz wielu wątków. Nie sądzę więc, żebyś kiedykolwiek musiał się martwić o to, co robi inny proces (w tym przypadku iOS) z bazą danych SQLite.

Edit: W celu wyjaśnienia, w dowolnym momencie zapisu do bazy danych, w tym prostym INSERT/UPDATE/DELETE, to automatycznie podejmuje wyłączną blokadę, napisz do bazy danych, a następnie zwolnić blokadę. (I rzeczywiście wymaga blokady SHARED, następnie blokady RESERVED, następnie blokady PENDING, a następnie blokady EXCLUSIVE przed zapisem.) Domyślnie, jeśli baza danych jest już zablokowana (powiedzmy z innego procesu), SQLite zwróci SQLITE_BUSY bez czekania . Możesz zadzwonić pod numer sqlite3_busy_timeout(), aby powiedzieć, że ma czekać dłużej.

+0

Kiedy mówisz "* nadal powinno się, powiedzmy, wziąć blokadę EXCLUSIVE przed napisaniem *", masz na myśli, że SQLite automatycznie zrobi to dla mnie? Lub że ja (lub framework SMS iOS) jestem za to odpowiedzialny? Na przykład, czy muszę (lub iOS) wydać instrukcję "BEGIN EXCLUSIVE TRANSACTION;" przed napisaniem? – Nate

+0

Dodałem zmianę. "BEGIN EXCLUSIVE TRANSACTION" służy do wykonania blokady EXCLUSIVE na początku transakcji. Domyślnie SQLite czeka tak długo, jak może. Z dokumentacji: * Zauważ, że polecenie BEGIN nie pozyskuje żadnych blokad w bazie danych. Po poleceniu BEGIN blokada SHARED zostanie uzyskana po wykonaniu pierwszej instrukcji SELECT. Blokada RESERVED zostanie uzyskana po wykonaniu pierwszej instrukcji INSERT, UPDATE lub DELETE. * ... –

+0

... * Nie blokuje się blokady EXCLUSIVE dopóki pamięć podręczna w pamięci nie zapełni się i musi zostać rozlana na dysk lub do momentu transakcji popełnia. W ten sposób system opóźnia blokowanie dostępu do odczytu do pliku pliku do ostatniej możliwej chwili. * Nawet, jeśli nie używasz opcji "BEGIN TRANSACTION", wszystkie instrukcje są nadal w transakcji niejawnej. –

2

Nie sądzę cokolwiek z tego jest dla ciebie nowość, ale kilka myśli:

chodzi o umożliwienie wielowątkowości (zarówno w odcinkach lub wielowątkowych), ogólna rada jest taka, że ​​można wywołaj sqlite3_config() (ale być może będziesz musiał najpierw wykonać wyłączenie zgodnie z sugestią w docs lub jak omówiono w artykule SO here), aby włączyć rodzaj wielowątkowości, który chcesz. Może to jednak mieć mniejszą przydatność, gdy nie masz kontroli nad tym, jakiego rodzaju dostęp iOS żąda sqlite i/lub tej bazy danych.

W ten sposób pomyślałem, że z perspektywy akademickiej nie byłoby bezpiecznie czytać tej systemowej bazy danych (ponieważ, jak pan twierdzi, nie ma się pewności, co system operacyjny robi). Ale nie zdziwiłbym się, gdyby iOS otwierał bazę danych przy użyciu dowolnego trybu domyślnego, więc z bardziej pragmatycznej perspektywy może być dobrze.

Oczywiście, dla większości użytkowników zainteresowanych dostępem wielowątkowym w ramach jednej aplikacji najlepszym rozwiązaniem byłoby pominięcie głupoty sqlite3_config() i po prostu zapewnienie skoordynowanego dostępu za pośrednictwem własnej kolejki szeregowej GCD (tzn. które przechodzą wszystkie interakcje z bazami danych, w ten sposób całkowicie eliminując problem wielowątkowości).Niestety, nie jest to opcja, ponieważ próbujesz skoordynować interakcję bazy danych z samym systemem iOS.

+0

dzięki za przemyślaną i dobrze napisaną odpowiedź. po pierwsze, o zamykaniu ... czy 'sqlite3_shutdown()' shutdown sqlite dla całego systemu operacyjnego, ponieważ jeśli tak, to wydaje się być również inny problem bezpieczeństwa wątków międzyprocesorowych. Myślę, że jedna niebezpieczna operacja może być lepsza niż robienie czegoś niebezpiecznego za każdym razem, gdy chcę przeczytać .db, ale może nie? – Nate

+0

Po drugie, kolejki GCD wydają się dobrym sposobem na koordynowanie dostępu między wieloma wątkami mojego autorstwa, ale to nie jest mój problem (moja aplikacja prawdopodobnie użyje tylko jednego wątku dla operacji sql). Jak zmusić iOS do korzystania z kolejek? czy też czegoś mi brakuje (zazwyczaj, gdy zadaję to pytanie, odpowiedź brzmi "tak"!) – Nate

+0

@Nate Odnośnie pierwszego pytania dotyczącego sqlite3_shutdown(), nie mogę odpowiedzieć na to pytanie. Właśnie cytowałem te inne odniesienia. Nie wydaje mi się to dobrym pomysłem, ale nie mogę powiedzieć. – Rob

Powiązane problemy