ďťż
 
[MS SQL] System transakcyjny wybieranie kolejnych rekordow ďťż
 
[MS SQL] System transakcyjny wybieranie kolejnych rekordow
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

[MS SQL] System transakcyjny wybieranie kolejnych rekordow



Krzysztof - 25-11-2006 00:07
[MS SQL] System transakcyjny wybieranie kolejnych rekordow
  Witam jestem tu nowy i nie wiem czy temat juz byl omawiany jesli tak to prosze o
info jak szukac bo sam nie znalazlem. A teraz do rzeczy.

Mam baze danych w ktorej w pojedynczych rekordach przechowywane sa unikalne
kody. Dzialanie systemu polega na wydawaniu unikalnych kodow. Kody naleza do
"paczkek" i maja byc wydawane zgodnie z zasada FIFO ale w obrebie paczek. Czyli
najpierw wydajemy kody z paczki pierwszej ale nie musimy juz kontrolowac ktory
to byl kod w paczce. Wazne zeby nie wydac dwa razy tego samego kodu. System
wydaje kody kilkadziesiat razy w ciagu doby. A problemem jest to ze zdarzaja mi
sie sytuacje zglaszane jako "deadlock" polega to na wydaniu wewnatrz procedury
tego samego kodu (rekordu) dla dwoch roznych procesow.
Moje rozwiazanie ktore ma zabezpieczac (choc nie zawsze to robi) nie wybranie
tego samego kodu jest pole "satus" w rekordzie z kodem ktore jest updatowane po
wybraniu kodu.
Prosze po podsunieci pomyslu jak cos takiego powinno wygladac bo jak widac moje
rozwiazanie jest niedoskonale.

Z gory dziekuje
Krzysztof

--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl





Grzesiek G. - 25-11-2006 00:07

  Krzysztof napisał(a):
> Witam jestem tu nowy i nie wiem czy temat juz byl omawiany jesli tak to prosze o
> info jak szukac bo sam nie znalazlem. A teraz do rzeczy.
>
> Mam baze danych w ktorej w pojedynczych rekordach przechowywane sa unikalne
> kody. Dzialanie systemu polega na wydawaniu unikalnych kodow. Kody naleza do
> "paczkek" i maja byc wydawane zgodnie z zasada FIFO ale w obrebie paczek. Czyli
> najpierw wydajemy kody z paczki pierwszej ale nie musimy juz kontrolowac ktory
> to byl kod w paczce. Wazne zeby nie wydac dwa razy tego samego kodu. System
> wydaje kody kilkadziesiat razy w ciagu doby. A problemem jest to ze zdarzaja mi
> sie sytuacje zglaszane jako "deadlock" polega to na wydaniu wewnatrz procedury
> tego samego kodu (rekordu) dla dwoch roznych procesow.
> Moje rozwiazanie ktore ma zabezpieczac (choc nie zawsze to robi) nie wybranie
> tego samego kodu jest pole "satus" w rekordzie z kodem ktore jest updatowane po
> wybraniu kodu.
> Prosze po podsunieci pomyslu jak cos takiego powinno wygladac bo jak widac moje
> rozwiazanie jest niedoskonale.

Ciężko coś poradzić bez znajomości schematu. W sumie chodzi o
odpowiednie blokady. Spróbuj coś takiego:
1. Oznaczenie kodu jako wydanego jednym updatem, bez wcześniejszych
selectów:
UPDATE tabela SET Status=Wydany,PID=@P@PID WHERE NumerPaczki=@Numer
paczki, NrKodu=(SELECT MAX(NrKodu)+1 FROM tabela WHERE
NumerPaczki=@NumerPaczki AND Status=Wydany)
2. Pobranie numeru paczki:
SELECT NumerPaczki FROM tabela WHERE NumerPaczki=@NumerPaczki AND PID =
@@PID.
3. Wyzerowanie PIDa po pobranym numerze paczki.

Oczywiście możne też zablokować tabelę na początku transakcji.

Pozdrawiam

PS: Deadlock to coś innego:-)

--
Grzegorz Gruza
Odpowiadając usuń "spamerom_nie." z adresu!!!




Grzesiek G. - 25-11-2006 00:07

  Zamiast @@PID miało być @@PROCID.

--
Grzegorz Gruza
Odpowiadając usuń "spamerom_nie." z adresu!!!




Artur - 25-11-2006 00:07

  By uniknąć deadloków możesz zrobić tak:

tabela
-------------
id kod
1 kod1
2 kod2
3 kod3
..........
gdzie id jest kolejnym numerem, a kod twoim kodem, który pobierasz.

Utworz indeks na id.

Utworz sekwencję w bazie, np. sekw1, która rozpoczyna się od 1 (np.
z parametrem cache np. 20, co będzie generowało paczki co 20-ścia
wartości).

w procedurze udpstępniającej kody pobierz następna wartość z
sekwencji (będzie unikatowa) i dla niej pobierz odpowiedni kod z bazy
o takim id -- masz gwartancję, że kolejne wywołania nie będą
pobierały tych samych rekordów. Po pobraniu rekordu uaktualnij
status, by później wiedzieć, czy rzeczywiście kod został pobrany.
Rekord powinieneś pobierać w trybie izolacji ANSI Repeatable Read, co
będzie oznaczało, że rekord odczytany będzie automatycznie
zablokowany do modyfikacji -- najpierw upewnisz się, czy rzeczywiście
kod nie został już wydany, a następnie zrobisz update. Ten poziom
izolacji gwarantuje, że nikt ci nie zmodyfikuje rekordu pomiędzy
odczytaniem a zapisem statusu dla tego rekordu. Tak na wszelki wypadek,
choć pewnie nie będzie to konieczne.

Jedyn problem to taki, że jeśli wycofasz transakcję, wtedy licznik
sekwencji będzie się kręcił dalej, a dany kod nie będzie wydany. W
takiej sytuacji co jakiś czas będziesz musiał zrobić coś z kodami,
które nie zostały wydane z tego powodu (znasz statusy), np
zwiększysz id na max(id) +1, wtedy będą wydane na samym końcu.

To tylko przykład, tak naprawdę nie wiem jakie sa założenia
"paczek" i znaczenie twoich kodów, ale jeśli są to np. kody do
telefonów na kartę, wtedy będzie działało szybko i bez deadloków.

-- Artur Wroński





Krzysztof - 26-11-2006 00:15

  Witam
{ciach}
> Ciężko coś poradzić bez znajomości schematu. W sumie chodzi o
> odpowiednie blokady. Spróbuj coś takiego:
> 1. Oznaczenie kodu jako wydanego jednym updatem, bez wcześniejszych
> selectów:
> UPDATE tabela SET Status=Wydany,PID=@P@PID WHERE NumerPaczki=@Numer
> paczki, NrKodu=(SELECT MAX(NrKodu)+1 FROM tabela WHERE
> NumerPaczki=@NumerPaczki AND Status=Wydany)
> 2. Pobranie numeru paczki:
> SELECT NumerPaczki FROM tabela WHERE NumerPaczki=@NumerPaczki AND PID =
> @@PID.
> 3. Wyzerowanie PIDa po pobranym numerze paczki.
>

Nie bardzo rozumiem jak to dziala, mozesz mi to wytlumaczyc?
>
> Oczywiście możne też zablokować tabelę na początku transakcji.
>
Nie wchodzi w gre.System jest na tyle obciazony ze spowodowaloby to totalna zapasc.

> Pozdrawiam
>
> PS: Deadlock to coś innego:-)

Tak wiem i tez najpierw szukalem klasyczneo deadlock'a szukalem trzy dni i nie
znalazlem i okazalo sie ze blad zglaszany jako deadlock to sytuacja gdy dwa
rozne procesy wybiora ten sam kod, Sam tego nie rozumiem ale tak jest.

Krzysztof

--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl




Krzysztof - 26-11-2006 00:15

  Witam

> By uniknąć deadloków możesz zrobić tak:
>
> tabela
> -------------
> id kod
> 1 kod1
> 2 kod2
> 3 kod3
> .........
> gdzie id jest kolejnym numerem, a kod twoim kodem, który pobierasz.
>
> Utworz indeks na id.
>
> Utworz sekwencję w bazie, np. sekw1, która rozpoczyna się od 1 (np.
> z parametrem cache np. 20, co będzie generowało paczki co 20-ścia
> wartości).
>
>
> w procedurze udpstępniającej kody pobierz następna wartość z
> sekwencji (będzie unikatowa) i dla niej pobierz odpowiedni kod z bazy
> o takim id -- masz gwartancję, że kolejne wywołania nie będą
> pobierały tych samych rekordów. Po pobraniu rekordu uaktualnij
> status, by później wiedzieć, czy rzeczywiście kod został pobrany.
> Rekord powinieneś pobierać w trybie izolacji ANSI Repeatable Read, co
> będzie oznaczało, że rekord odczytany będzie automatycznie
> zablokowany do modyfikacji -- najpierw upewnisz się, czy rzeczywiście
> kod nie został już wydany, a następnie zrobisz update. Ten poziom
> izolacji gwarantuje, że nikt ci nie zmodyfikuje rekordu pomiędzy
> odczytaniem a zapisem statusu dla tego rekordu. Tak na wszelki wypadek,
> choć pewnie nie będzie to konieczne.
>
> Jedyn problem to taki, że jeśli wycofasz transakcję, wtedy licznik
> sekwencji będzie się kręcił dalej, a dany kod nie będzie wydany. W
> takiej sytuacji co jakiś czas będziesz musiał zrobić coś z kodami,
> które nie zostały wydane z tego powodu (znasz statusy), np
> zwiększysz id na max(id) +1, wtedy będą wydane na samym końcu.
>

Prezentowany tu przyklad byl juz brany pod uwage i staam go obok wybierania nie
kolejnego ale losowego kodu z paczki. Nie zdecydowalem jeszcze ktory bedzie
lepszy. Losowanie kodu nie powoduje koniecznosci pisania po tablelach co chyba w
moim przypadku bedzie szybsze.

> To tylko przykład, tak naprawdę nie wiem jakie sa założenia
> "paczek" i znaczenie twoich kodów, ale jeśli są to np. kody do
> telefonów na kartę, wtedy będzie działało szybko i bez deadloków.

Zagadnienie o ktore pytam sprowadza sie bo prostego schematu:

tKody:
id_kodu | kod | nr packi | status | dodatkowe_dane
-------------------------------------
1 | k1 | 1 | 1 | dane1
2 | k2 | 1 | 1 | dane1
3 | k3 | 1 | 1 | dane1
4 | k4 | 1 | 1 | dane1

dane dodatkowe sluza do usciclenia jaki kod ma zostac wybrany.

i tak jak wybieram

SELECT kod FROM tKody WHERE dodatkowe_dane = dane1 AND nr paczki = 1 AND status = 1

to dostaje kod k1

i chce osognac taki stan zeby kolejny proces ktory pyta o kod nie dostal juz k1
tylko k2. A dzis mam taki san ze zdarza sie ze dwa procesy dostaja tn sam kod.

Dzis kody pobieram tak:

UPDATE tKody
SET status=2, kod = '-1', @code=kod
WHERE id_kodu IN (
SELECT TOP 1 id_kodu FROM tKody
WHERE tKody.dodatkowe_dane = dane1
AND (tKody.status=1)
)

Jak mozna latwo zauwazyc @code zawiera ko ktory wybieram.
Informacja dodatkowa po pobraniu zmienim wartosc kodu na "-1" tak zeby\u juz
nigdy nie byl uzyty, co oznacza ze dwa procesy odpytuja baz na tyle szybko ze
"ten drugi" trafia jeszcze w kod przed zmiana jego wartosci na "-1"

Pozdrawiam
Krzysztof

--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl




Grzesiek G. - 14-12-2006 16:08

  Krzysztof napisa?(a):
> Witam
> {ciach}
>
>>Ci??ko co? poradzi? bez znajomo?ci schematu. W sumie chodzi o
>>odpowiednie blokady. Spróbuj co? takiego:
>>1. Oznaczenie kodu jako wydanego jednym updatem, bez wcze?niejszych
>>selectów:
>>UPDATE tabela SET Status=Wydany,PID=@P@PID WHERE NumerPaczki=@Numer
>>paczki, NrKodu=(SELECT MAX(NrKodu)+1 FROM tabela WHERE
>>NumerPaczki=@NumerPaczki AND Status=Wydany)
>>2. Pobranie numeru paczki:
>>SELECT NumerPaczki FROM tabela WHERE NumerPaczki=@NumerPaczki AND PID =
>>@@PID.
>>3. Wyzerowanie PIDa po pobranym numerze paczki.
>>
>
>
> Nie bardzo rozumiem jak to dziala, mozesz mi to wytlumaczyc?
>

W sumie to niedok?adny kod, tak?e pewnie nie dzia?a :-. Moja idea by?a
taka, ?eby oznacza? zarówno, ?e paczka jest zaj?ta (aktualizacja
statusu) jak i kto zaj?? (ustawienie @@PROCID). W powi?zaniu, z
odpowiednim poziomem izolacji transakcji (read uncomited) i granulacj?
blokad (ROWLOCK) nie b?dzie trzeba czeka? na pobieranie kolejnych
numerów. Oczywi?cie, dopuszcza to mo?liwo?? powstawania dziur - jak przy
identity:-(.

Dodanie aktualizacji @@PROCID umo?liwi pó?niejsze znalezienie numeru,
który zosta? przez proces zarezerwowany.

>>Oczywi?cie mo?ne te? zablokowa? tabel? na pocz?tku transakcji.
>>
>
> Nie wchodzi w gre.System jest na tyle obciazony ze spowodowaloby to totalna zapasc.
>

Tak my?la?em. Rzuci?em tak? oczywist? propozycj?, bo blokowanie od razu
ca?ej tabeli pozwala unikn?? problemu eskalacji blokad i bywa
rozwi?zaniem wystarczaj?co wydajnym.

>
>>Pozdrawiam
>>
>>PS: Deadlock to co? innego:-)
>
>
> Tak wiem i tez najpierw szukalem klasyczneo deadlock'a szukalem trzy dni i nie
> znalazlem i okazalo sie ze blad zglaszany jako deadlock to sytuacja gdy dwa
> rozne procesy wybiora ten sam kod, Sam tego nie rozumiem ale tak jest.

Rzeczywi?cie dziwne. Mo?e by nale?a?o zg?osi? problem do M$?

Pozdrawiam

--
Grzegorz Gruza
Odpowiadaj?c usu? "spamerom_nie." z adresu!!!
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    jak to =?ISO-8859-2?Q?zrobi=E6=2E=2E=2E=3F_TSQL_sql_server?==?ISO-8859-2?Q?_?= =?iso-8859-2?Q?=5BMS_SQL=5D_Czy_mo=BFna_wywo=B3a=E6_funkcje_t ylko_raz_dla?==?iso-8859-2?Q?_ca=B3ego_zbioru_=BCr=F3d=B3owego=3F?= [MSSQL] =?ISO-8859-2?Q?zgodno=B6ci_z_licencjami_Microsoft_?==?ISO-8859-2?Q?SQL_Server?= Oracle PL/SQL Wstawianie =?ISO-8859-2?Q?wynik=F3w_kolekcji_d?==?ISO-8859-2?Q?o_tabeli?= [MSSQL] ACCESS - SQL =?ISO-8859-2?Q?B=B3ad_w_konwersji_lic?==?ISO-8859-2?Q?zb?= =?iso-8859-2?Q?=5Bmssql=5D_Zapytania_rekurencyjne__-_czy_sk=B3adnia_sql?==?iso-8859-2?Q?_co=B6_takiego_przewiduje_=3F?= =?iso-8859-2?Q?=5BMySQL=5D_Co_minimalnie_potrzebne_zeby_mie=E 6_klienta_My?==?iso-8859-2?Q?SQL_na_Linuxie=3F?= [oracle] - Oracle SQL Developer - co to jest SID? =?ISO-8859-2?Q?[Oracle]_Wywo=B3anie_skryptu_sh_z_PL/SQL-a=3F=3F?= [oracle] Baza danych do kursy Introduction to Oracle9i:PL/SQL ? Skąd ją pobrać ?
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • autwywalczyl.opx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com