Mechanizm sekwencji w bazach danych

0

Niektóre bazy danych mają coś takiego jak Sekwencję do wyznaczania numerów PK nowo wstawianych rekordów. Z tego co się dowiedziałem (mogę się mylić) MySQL (5,2) nie wspiera jeszcze tego rozwiązania a ma za to funkcje AutoIncrement. Nie bardzo orientuje się w założeniach działania tej Sekwencji a na moim MySQL tego nie popróbuję. Dlatego mam pytanko o ogólne działanie Sekwencji. Rozumiem że jest to mechanizm mający zapewnić bezpieczne, wielowątkowe działania Insertów na tabeli. Czyli blokuje to inne wątki na czas wykonania insertu w pierwszym wątku? Czy sekwencje definiuje się dla tabeli? (każda tabela może mieć swoją?)
Jak ta Sekwencja wypada w porównaniu z MySQL'owym AutoIncrement?

0

?
Sekwencja to jest po prostu pewien mechanizm generowania wartości (niekoniecznie kluczy!) według zadanego algorytmu. Możesz mieć ile chcesz sekwencji dla dowolnej ilości tabel. Nie zapewnia to żadnego wielowątkowego insertowania. Zapewnia jedynie tyle że każde pobranie wartości z sekwencji zwróci kolejną wartość. AutoIncrement to taka prymitywna sekwencja która zwraca kolejne wartości (1,2,3...)
Sekwencje pozwalają za to zwracać wartości, jak juz wspomniałem, wg algorytmu. To znaczy że mozesz napsiać sekwencje która będzie zwracać tylko parzyste wartości etc.

1

Sekwencja nie jest izolowana na poziomie transakcji, jest to zupełnie niezależny mechanizm i tym przede wszystkim różni się od AUTO_INCREMENT. Sekwencja zwraca kolejne wartości na żądanie i nie blokuje transakcji na czas wykonania INSERT, przez to również nie cofa się w przypadku ROLLBACK. Jeżeli jedna z wielu transakcji uruchomionych jednocześnie z jakiś przyczyn się nie wykona to będziesz miał dziurę w numeracji.

0

Dzięki wielkie.
Dopytam jeszcze o coś. Czy sekwencja, po restarcie serwera bazy danych, aby podać kolejną wartość dla danej kolumny, danej tabeli (dla np. komendy insert) sczytuje ostatnią przydzielona wartość z tej kolumny czy też ma niezależnie zapamiętaną tą następna wartość gdzieś w swoim zakresie pamięci (pamięci trwałej, niekasowanej podczas wyłączenie serwera)?
Chodzi mi o taką sytuację gdy:
Mamy tabelę w której kolumna PK to int z przypisaną sekwencją (1, 2, 3, 4 .... itd) która ma go wypełniać automatycznie.
Przed wyłączeniem serwera usuwam ostatni rekord z tabeli (rekord o jakimś największym numerze PK np. = 11). Czy teraz po restarcie serwera, gdy będę dokonywał kolejnego Insertu do tej tabeli to nowy rekord dostanie numer PK = 11 bo w tabeli ostatnim rekordem jest PK = 10 czy też dostanie numer 12 bo sekwencja pamięta ostatnio nadana liczbę?
Jak robiłem ten test w MySQL dla AutoIncrement to gdy usunąłem taki rekord (nr 11), nie wyłączałem bazy, a potem dodawałem nowy to ten nowy dostawał kolejny numer czyli 12. Miałem wiec numeracje rekordów ... 9, 10, 12. Jeżeli pomiędzy tymi procesami usunięcia i dodania wyłączyłem serwer to nowy rekord miał numer 11 (... 9, 10, 11 ). AutoIncrement nie pamiętał więc danych z poprzedniej sesji działania serwera. Czy tak samo jest dla Sekwencji?

Pytanie do Shalom bo odnośnie Javy:
Wybranie dla encji strategi generowania @GeneratedValue(strategy=TABLE, generator="CUST_SEQ") tworzy w bazie specjalną tabelę w której przechowywane są wartości nowych danych do PK dla tworzonych obiektów encji (i rekordów). Czy ta tabela (mechanizm tego generatora) jest wykorzystywana tylko przez Javę? Czy też jest to mechanizm samej bazy danych i można go jakoś uruchomić przy dodawaniu nowych rekordów do danej tabeli za pomocą wiersza poleceń?

0

@AdamPL: identity (odpowiednik autoincrement z mysql) w mssql również nie blokuje transakcji, a rollback nie przywraca początkowego stanu licznika.

0

@Pierce111 nic nie rozumiesz z tych sekwencji.

  1. Są zapisywane oddzielnie, bo możesz używać jednej sekwencji w wielu atrybutach wielu tabel jednocześnie! Sekwencje się NIE COFAJĄ!
  2. Twój wniosek z jakimś "niepamiętaniem danych z poprzedniej sesji" to nie wiem skąd wziąłeś.
  3. Nie rozumiem pytania. To co pokazałeś to po prostu ustawienie sekwencji z której mają być pobierane wartości dla danego atrybutu encji. To nie jest żaden javowy mechanizm, tylko podpięcie Javy do sekwencji danej bazy.
0

@Pierce111 - Sekwencja to obiekt istniejący w bazie danych niezależnie od tabeli. Usuwanie rekordów nie wpływa na to jaką wartość zwróci. Jeżeli sekwencja zwróciła 11, to następną wartością będzie 12 bez względu na to czy usuniesz rekordy.

@ŁF - IDENTITY to jeszcze coś innego niż AUTO_INCREMENT albo sekwencja (SEQUENCE), a to dlatego, że jest podobna do AUTO_INCREMENT pod tym względem, że jest na jednej konkretnej kolumnie, w jednej konkretnej tabeli, w odróżnieniu od sekwencji, która jest niezależna od tabeli i kolumny, jest również podobna do sekwencji właśnie w taki sposób jak to napisałeś. Jednak IDENTITY to nie sekwencja. Sekwencja pojawia się dopiero w MSSQL 2011 (znanym również jako 2008R2).

0

Do Shalom.
Przypadek jaki opisałem powyżej zachodzi dla zastosowania** AutoIncrement** w MySQL. Czyli po wyłączeniu serwera bazy MySQL, dla kolumny AutoIncrement następna wartość określana jest na podstawie zawartości tej kolumny. Nie wiem jak jest dla Sekwencji bo nie mam zainstalowanej bazy na której działają sekwencję (inaczej szybko bym sobie zrobił taki teścik). Dlatego pytam czy jest może tak samo jak dla powyższego przypadku z ** AutoIncrement** w MySQL.
Nie stwierdzam faktu tylko pytam o działanie.

1

Podsumowując:

  1. AUTO_INCREMENT(MySQL)
  • można założyć na jednej konkretnej tabeli, na jednej konkretnej kolumnie
  • w przypadku usunięcia rekordu nie cofa się (chyba, że wyłączysz serwer jak sam to sprawdziłeś)
  • generuje kolejney numer, nawet jeżeli transakcja została cofnięta (ROLLBACK) //poprawione
  1. Sekwencja(MSSQL i Oracle)
  • niezależny obiekt w bazie danych, jeden może być używany w wielu tabelach i polach jednocześnie
  • w przypadku usunięcia rekordu nie cofa się
  • generuje kolejny numer, nawet jeżeli transakcja została cofnięta (ROLLBACK)
  1. IDENTITY(MSSQL)
  • można założyć na jednej konkretnej tabeli, na jednej konkretnej kolumnie
  • w przypadku usunięcia rekordu nie cofa się
  • generuje kolejny numer, nawet jeżeli transakcja została cofnięta (ROLLBACK)

/edit: Jeszcze jedna uwaga do AUTO_INCREMENT. Jeżeli pole AUTO_INCREMENT jest częścią wielokolumnowego klucza głównego np. PRIMARY KEY(id, wartosc) to id jest generowane niezależnie dla każdej unikalnej kobinacji, co doprowadza do sytuacji, że możemy mieć wiele rekordów o tym samym id w tej samej tabeli.

CREATE TABLE tabela 
(
  id INT NOT NULL AUTO_INCREMENT 
 ,wartosc VARCHAR(100) NOT NULL
 ,PRIMARY KEY(id, wartosc)
);
INSERT INTO tabela(wartosc) VALUES ('Kowalski');
INSERT INTO tabela(wartosc) VALUES ('Kowalski');
INSERT INTO tabela(wartosc) VALUES ('Nowak');
INSERT INTO tabela(wartosc) VALUES ('Kowalski');
INSERT INTO tabela(wartosc) VALUES ('Nowak');
id wartosc
1 Kowalski
2 Kowalski
1 Nowak
3 Kowalski
2 Nowak

// pozwoliłem sobie poprawić zdublowany tekst - ŁF

0
AdamPL napisał(a):

Podsumowując:

  1. Sekwencja(MSSQL i Oracle)
  • generuje kolejny numer, nawet jeżeli transakcja została cofnięta (ROLLBACK)

A będąc ścisłym - numer nie mniejszy niż poprzednio użyty. Uzywając sekwencji w bazie Oracle nie masz gwarancji, że nie usuwając rekordów bedziesz je mieć ponumerowane od 1 do 99999999. Luki w numeracji moga powstać, i powstaną na pewno, jeżeli baza zostanie zatrzymana. Wynika to z tego, że Oracle DB pobiera z sekwencji cała serię kolejnych "numerów" (a nie kazdy pojedynczo) i trzyma je w specjanym cache'u o ustalonym rozmiarze, jednoczesnie zapisując w sekwencji, że pobrano np. 20 rekordów. Jezeli w tym momencie zresetujesz baze, stracisz wszystko, co było w cache'u - i zostanie pobrany nastepny bufor numerów (kolejna 20).

0

@AdamPL: Dzięki za wyczerpujący opis.

0

Zrobiłem drobne sprawdzenie dla AutoIncrement w MySQL przy Rollbacku.
Jednak generuje nowy numer przy rollbackowanej operacji Insert.
Trzeba by poprawić:

  1. AUTO_INCREMENT(MySQL)
  • można założyć na jednej konkretnej tabeli, na jednej konkretnej kolumnie
  • w przypadku usunięcia rekordu nie cofa się (chyba, że wyłączysz serwer jak sam to sprawdziłeś)
  • nie generuje kolejnego numeru, jeżeli transakcja została cofnięta (ROLLBACK)
0

@Pierce111 - Rzeczywiście, kiedyś działało to tak jak opisywałem, ale teraz jest tak jak napisałeś. Sprawdziłem w dokumentacji i numerek generowany przez AUTO_INCREMENT w rollbackowanej transakcji powinien zostać stracony. Zdaje się, że silnik InnoDB zachowuje się tak od wersji 5.1.22 kiedy to został wprowadzony parametr innodb_autoinc_lock_mode, którym można ustawić jak zachowuje się AUTO_INCREMENT.

0

No to mamy pełne zestawienie. Dobrze że twórcy serwerów baz dążą do pewnej unifikacji działań poleceń.

1 użytkowników online, w tym zalogowanych: 0, gości: 1