2013-06-09 4 views
5

Znam różnicę między czytnikiem danych a zestawem danych.Czy czytnik danych jest lepszy lub zestaw danych do aplikacji, w której możemy mieć problem z współbieżnością

DataReader to lepszy wybór dla aplikacji wymagających zoptymalizowanego dostępu tylko do odczytu, szybkiego i do przodu.

Zestaw danych jest lepszy dla aplikacji, w której można uzyskać wszystkie dane i zaktualizować je zgodnie z potrzebami na poziomie aplikacji i przesłać zmianę do bazy danych.

Proszę wyjaśnić, jeśli coś jest nie tak z moim zrozumieniem.

Teraz miałem wywiad, w którym ktoś mnie zapytał. Czy datareader lub architektura podłączona jest odpowiednia do zastosowań takich jak system biletowy. Zasadniczo miała na myśli, że wielu użytkowników może próbować zaktualizować tę samą tabelę. Tak więc pojawia się koncepcja Współbieżności.

Możemy użyć Rozłączonej architektury, aby sprawdzić współbieżność i pozwolić, aby tylko jeden użytkownik aktualizował tabelę na raz. Ale nie wiem, jak to się dzieje w kategoriach połączonej architektury. Czy połączenie z bazą danych, a w szczególności z tą tabelą, spowoduje, że tylko jeden użytkownik wykona aktualizację, a inni, którzy spróbują uderzyć później, nie będą w stanie tego zrobić.

Nie wpłynie to na wydajność, jeśli wszyscy użytkownicy otworzyli połączenie, ponieważ baza danych dotrze do szyjki butelki.

Mam nadzieję, że otrzymam odpowiedź, aby je zrozumieć.

Odpowiedz

4

Myślę, że nie jest to kwestia tego, która z nich jest lepsza, ponieważ dane są już stare/nieprawidłowe po dotarciu do klienta. Pokazanie tabeli rezerwacji może być przydatne, aby uzyskać przybliżony widok zastrzeżeń, ale może to być zupełnie inna sytuacja w ciągu następnej sekundy. Chcesz wyeliminować warunki wyścigu. Na początek potrzebna jest dobra architektura.

Jednym ze sposobów, aby to zrobić, jest "zarezerwowanie" biletu [1]. Aplikacja prosi o uzyskanie biletu, który jest dostępny z uwzględnieniem pasujących kryteriów. W tym momencie znany jest fakt, czy bilet jest dostępny, czy nie. Jeśli był dostępny, był już zarezerwowany. Pozwala to uniknąć wielokrotnych rezerwacji dla jednego biletu. Następna rezerwacja (ta sama operacja/działanie) spowoduje zarezerwowanie innego biletu. Zawsze możesz dodać informacje do tego biletu (na przykład właściciela biletu i jego informacji), jeśli jest to wymagane. Bilety, które nie mają dołączonej do niego informacji, przekroczą limit czasu po określonej ilości minut i wrócą do puli. Bilety te można ponownie "zarezerwować" [1].

[1] Aby uniknąć wielu przydziałów, należy użyć optimistic locking.

Aby odpowiedzieć na pytanie, powiedziałbym: DataReader. Utrzymuje komunikację z bazą danych na minimalnym poziomie (ładowanie i blokowanie), dzięki czemu może obsłużyć aktualizacje tak szybko, jak to możliwe. Pamiętaj, że wybieranie jednego z drugim nie rozwiązuje problemów związanych z współbieżnością. Ważne jest całkowite rozwiązanie.

Przykład

nie wiem wymagania, ale ponieważ jest to pytanie wywiad dam przykład. Nie traktuj tego jako złotej reguły, ale z końcówki mojej głowy będzie to coś takiego:

(jeśli jest to wymagane) Najpierw na ekranie pojawi się ekran, na którym w systemie pozostały bilety, zarezerwowany. Otwórz połączenie i czytnik, aby odczytać liczbę biletów dostępnych do rezerwacji. Zamknij czytnik i połączenie. Użytkownik przechodzi do następnego ekranu.

SELECT COUNT(*) 
FROM [Tickets] 
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout)) 
    AND [TickedAssignedToUserId] IS NULL; 

Użytkownik żąda x-kwoty biletów i przechodzi do następnego ekranu. W tym momencie system sprawdza z optymistycznym blokowaniem, czy dostępnych jest wystarczająco dużo biletów. Wystarczy otworzyć połączenie i wykonać następujące zapytanie (z transakcji!):

UPDATE TOP(@numberOfTicketsRequested) [Tickets] 
SET [LastReserved]=GETDATE() 
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout)) 
    AND [TickedAssignedToUserId] IS NULL; 

Liczbę wierszy powinna być taka sama jak @numberOfTicketsRequested. W takim przypadku zatwierdz transakcję i uzyskaj identyfikator biletu. W przeciwnym razie cofnij i poinformuj użytkownika, że ​​nie ma już biletów. W tym momencie potrzebujemy informacji o rekordach, więc warto również uzyskać identyfikator.

W tym momencie użytkownik otrzymuje @ticketTimeout ilość minut na podanie danych użytkownika. Jeśli wykonane prawidłowo, poniższe zapytanie może być wykonane:

UPDATE TOP(@numberOfTicketsRequested) [Tickets] 
SET [TickedAssignedToUserId][email protected] 
WHERE [TicketId][email protected] AND [LastReserved][email protected] AND [TickedAssignedToUserId] IS NULL; 

Jeśli użytkownik trwało dłużej niż, powiedzmy 10 minut, a ktoś inny wniosek ponownie ten sam bilet, wtedy LastReserved timestamp nie zmieniło. Kiedy pierwszy użytkownik próbował zarezerwować bilet ze swoimi szczegółami, aktualizacja nie jest już zgodna z oryginalnym znacznikiem czasu LastReserved, a aktualizacja pokaże niewystarczającą ilość wierszy, których dotyczy (= wycofanie). Jeśli pasuje do liczby dotkniętych wierszy, użytkownik pomyślnie zarezerwował bilety (= commit).

Należy pamiętać, że do zgłoszenia nie dotarły żadne informacje o biletach, z wyjątkiem identyfikatorów biletów. Nie mam również rejestracji użytkownika. Żadne pełne tabele nie są przekazywane, a blokady są używane tylko minimalnie (tylko na dwie krótkie aktualizacje).

+0

Dzięki za link na temat optymistycznego blokowania. Więc Współbieżność zostanie definitywnie rozwiązana przez to. Jeśli wielu użytkowników próbuje pobrać dostępne bilety, a następnie próbuje zarezerwować bilet. Ponieważ dzięki połączeniu DataReader zawsze pozostaje otwarte. Więc nie wpłynie to na obciążenie serwera bazy danych. Jeśli skorzystam z opcji Disconnected Architecture Locking, można zastosować i obciążenie serwera bazy danych będzie mniejsze. Tak, problemy z pamięcią będą tam, ale które będą bardziej problematyczne z wydajnością, obciążenie serwera bazy danych lub problem z pamięcią. – user2432715

+0

Jako sidenote: 'DataReader' implementuje' IDisposable', więc zasoby (połączenie) zostaną zwrócone do puli połączeń. W tej chwili można używać innych czytników/zapisów ze względu na dostępne połączenie, zwiększając przepustowość. Pamiętaj, że wspomniany zamek nie jest tradycyjną blokadą (nie blokuje się, dopóki nie zwolnisz jej ponownie). – Caramiriel

+0

Oto kolejne kroki, które należy wykonać, aby efektywnie korzystać z DataReadera: 1. Otwórz połączenie 2. Pokaż dane użytkownikowi za pomocą narzędzia DataReader. 3. Zamknij połączenie (tutaj zasób będzie bezpłatny) Teraz nadchodzi aktualizacja. Użytkownik zaktualizuje teraz rekord. 4. Ooen Connection again 5. użyj czytnika danych, aby zaktualizować dany rekord. 5. Zamknij. Blokowanie stosowane odpowiednio – user2432715