Hibernacja: hbm2ddl.auto = aktualizacja w produkcji?


339

Czy można uruchamiać aplikacje Hibernacji skonfigurowane hbm2ddl.auto=updatedo aktualizowania schematu bazy danych w środowisku produkcyjnym?


6
Robimy to. Nigdy nie miałem żadnych problemów.
cretzel

4
Bardzo dobre pytanie. Stawię temu czoła. Więc teraz 2018 - po 10 latach, co sądzisz? Czy bezpiecznie jest używać aktualizacji Hibernacji w produkcyjnych bazach danych ważnych klientów ze złożonymi schematami?
Kirill Ch

Odpowiedzi:


388

Nie, to niebezpieczne.

Pomimo najlepszych starań zespołu Hibernacja, po prostu nie możesz polegać na automatycznych aktualizacjach w produkcji . Napisz własne łatki, przejrzyj je za pomocą DBA, przetestuj je, a następnie zastosuj ręcznie.

Teoretycznie, jeśli aktualizacja hbm2ddl działała w fazie rozwoju, powinna również działać w fazie produkcyjnej. Ale w rzeczywistości nie zawsze tak jest.

Nawet jeśli zadziałało OK, może nie być optymalne. DBA płaci się tyle z jakiegoś powodu.


33
Dlaczego to jest niebezpieczne?
cretzel

74
Jest to niebezpieczne, ponieważ zastosowane łaty mogą mieć skutki uboczne, których hbm2ddl prawie nie może przewidzieć (takie jak wyłączenie wyzwalaczy zainstalowanych dla modyfikowanej tabeli). W przypadku złożonych schematów najbezpieczniejszym sposobem jest ręczne. Automatyczne z testami po regresji jest odległe na sekundę. Wszystkie IMHO.
Vladimir Dyuzhev

18
Również aktualizowanie schematu db powinny być obsługiwane przez profesjonalistów (dbas). Odzyskiwanie po złej zmianie db jest w najlepszym razie trudne. Vova nie wspomniała o tym - ale co się stanie, jeśli aktualizacja hibernacji zdecyduje się upuścić kolumnę i dodać ją ponownie, ponieważ zmienił się typ lub rozmiar. Powiedzmy, że kolumna zawiera adresy e-mail wszystkich użytkowników? :-) pa, pa pa ..... Chcesz, aby zmiana DDL była generowana automatycznie - ale absolutnie chcesz, aby zmiana była sprawdzana przez człowieka.
Pat

9
nie tworzysz kopii zapasowych baz danych przed aktualizacją?
Jacob

21
Fwiw, w tej chwili aktualizacja schematu Hibernacji nie upuszcza tabel ani kolumn.
Brian Deterling

70

Robimy to w produkcji, chociaż z aplikacją, która nie jest krytyczna dla misji i bez wysoko płatnych DBA dla personelu. To tylko jeden mniej ręczny proces, który jest obarczony ludzkim błędem - aplikacja może wykryć różnicę i zrobić właściwą rzecz, a także prawdopodobnie przetestowałeś ją w różnych środowiskach programistycznych i testowych.

Jedno zastrzeżenie - w środowisku klastrowym możesz tego uniknąć, ponieważ wiele aplikacji może jednocześnie wyświetlać i modyfikować schemat, co może być złe. Lub zastosuj jakiś mechanizm, w którym tylko jedna instancja może zaktualizować schemat.


2
Używamy go również w produkcji, w podobnym przypadku użycia. Platforma analityczna, która nie jest krytyczna dla misji. Wdrożyliśmy 16 000 razy w 4 środowiskach (4 lata) bez tak dużego problemu z hibernacją. Jesteśmy małym zespołem i wszyscy jesteśmy głównie początkującymi SQL RDBS i mamy większą wiarę w schemat obsługi Hibernacji niż my sami. Zastanawiam się, jaki jest poziom błędu posiadania DBA w przypadku personelu zarządzającego migracjami i zmianami schematu? Czy to jest lepsze niż 0 w wdrożeniach ~ 16K?
user3263752

Co powiesz na ten komentarz przez pat? stackoverflow.com/questions/221379/…
Shiva kumar

52

Twórcy Hibernacji odradzają to w środowisku produkcyjnym w swojej książce „Java Persistence with Hibernate” :

OSTRZEŻENIE: Widzieliśmy użytkowników Hibernacji próbujących użyć SchemaUpdate do automatycznej aktualizacji schematu produkcyjnej bazy danych. Może to szybko zakończyć się katastrofą i nie pozwoli na to DBA.


1
Czy to zostało napisane w 2006 roku?
user3263752

28

Sprawdź LiquiBase XML, aby uzyskać dziennik zmian aktualizacji. Nigdy nie korzystałem z niego aż do tego roku, ale odkryłem, że bardzo łatwo jest się nauczyć i sprawić, że kontrola wersji DB / migracja / zarządzanie zmianami jest bardzo niezawodna. Pracuję nad projektem Groovy / Grails, a Grails używa Hibernacji pod spodem dla wszystkich swoich ORM (zwanych „GORM”). Używamy Liquibase do zarządzania wszystkimi zmianami schematu SQL, co robimy dość często, ponieważ nasza aplikacja ewoluuje z nowymi funkcjami.

Zasadniczo przechowujesz plik XML zestawów zmian, które dodajesz w miarę ewolucji aplikacji. Ten plik jest przechowywany w git (lub cokolwiek, którego używasz) z resztą projektu. Kiedy twoja aplikacja jest wdrożona, Liquibase sprawdza swoją tabelę dzienników zmian w DB, z którą się łączysz, aby wiedział, co zostało już zastosowane, a następnie inteligentnie stosuje tylko te zestawy zmian, które nie zostały jeszcze zastosowane z pliku. Działa absolutnie świetnie w praktyce, a jeśli użyjesz go do wszystkich zmian schematu, możesz być w 100% pewien, że kod, który pobierasz i wdrażasz, zawsze będzie w stanie połączyć się z w pełni kompatybilnym schematem bazy danych.

Niesamowite jest to, że mogę wziąć całkowicie pustą bazę danych mysql na moim laptopie, odpalić aplikację i od razu skonfigurować dla mnie schemat. Ułatwia także testowanie zmian schematu przez zastosowanie ich najpierw do lokalnego dewelopera lub tymczasowej bazy danych.

Najłatwiejszym sposobem na rozpoczęcie jest prawdopodobnie zabranie istniejącej bazy danych, a następnie użycie Liquibase do wygenerowania początkowego pliku baseline.xml. Następnie w przyszłości możesz po prostu do niego dołączyć i zezwolić Liquase na zarządzanie zmianami schematu.

http://www.liquibase.org/


Idealne, właśnie to, co miałem zamiar przenieść. Wydaje mi się, że najlepszą rzeczą jest pójść o krok dalej, aby dodać hbm2ddl.auto=update, aby twoje mapowania Class / DB były sprawdzane i abyś miał pełną kontrolę nad tworzeniem DB poprzez Liquibase. Co myślisz?
bholagabbar

Ups, miałem na myślivalidate
bholagabbar

Liquibase jest lepszy w zarządzaniu skryptami za pomocą obsługi „dołącz-import” i obsługi wersjonowania oraz atrybutu „Typ” dla plików, który pomaga mieć różne pliki SQL dla różnych środowisk mających relacje z rodzicem-dzieckiem. w skrócie, Idź tradycyjny SQL Mgmt. w produkcji. Do rozwoju potrzebujemy prędkości produkcji, potrzebujemy gwarancji, stabilności i kopii zapasowych.
Karan Kaw

26

Głosowałbym na nie. Hibernacja wydaje się nie rozumieć, kiedy zmieniły się typy danych dla kolumn. Przykłady (przy użyciu MySQL):

String with @Column(length=50)  ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)

@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed

Prawdopodobnie istnieją też inne przykłady, takie jak zwiększenie długości kolumny String o ponad 255 i przekonwertowanie jej na tekst, średni tekst itp.

To prawda, nie sądzę, aby naprawdę istniał sposób na „konwersję typów danych” bez tworzenia nowej kolumny, kopiowania danych i niszczenia starej kolumny. Ale w chwili, gdy baza danych ma kolumny, które nie odzwierciedlają obecnego mapowania Hibernacji, żyjesz bardzo niebezpiecznie ...

Flyway to dobra opcja na rozwiązanie tego problemu:

http://flywaydb.org


1
Właśnie wypróbowałem pierwszą część twojego przykładu - w moim przypadku zmieniłem @Column(length = 45)na @Column(length = 255). Może sprawdzić, czy Hibernacja 4.3.6. Finał poprawnie zaktualizował schemat bazy danych za pomocą hbm2ddl.auto=update. (Należy wspomnieć, że w bazie danych nie ma obecnie żadnych danych - tylko jej struktura).
Steve Chambers

Bardzo możliwe, że naprawili ten błąd gdzieś w ciągu ostatnich ~ 6 lat. Jeśli jednak masz dane w schemacie i dokonałeś zmiany, która spowodowała zmniejszenie szerokości kolumny, wystąpią błędy lub niezarządzane obcięcie danych.
cliff.meyers

1
flywaydb potrzebuje ręcznie skryptu SQL, powinien być lepszy niż to, co potrafi automatyczny program, ale kto może napisać duży skrypt, to problem.
Bung Rikimaru,

25

Hibernacja musi umieścić oświadczenie o nieużywaniu automatycznych aktualizacji w prod, aby zakryć się, gdy ludzie, którzy nie wiedzą, co robią, używają go w sytuacjach, w których nie należy go używać.

Przyznaję, że sytuacje, w których nie należy go używać, znacznie przewyższają liczbę przypadków, w których jest w porządku.

Używałem go od lat do wielu różnych projektów i nigdy nie miałem ani jednego problemu. To nie jest kiepska odpowiedź i nie jest to kodowanie kowboja. To fakt historyczny.

Osoba, która mówi „nigdy nie rób tego w produkcji”, myśli o określonym zestawie wdrożeń produkcyjnych, a mianowicie tych, które zna (jego firma, branża itp.).

Wszechświat „wdrożeń produkcyjnych” jest ogromny i zróżnicowany.

Doświadczony programista Hibernacja dokładnie wie, co DDL będzie wynikało z danej konfiguracji mapowania. Dopóki testujesz i potwierdzasz, że to, czego oczekujesz, kończy się w DDL (w dev, qa, inscenizacji itp.), Wszystko jest w porządku.

Gdy dodajesz wiele funkcji, automatyczne aktualizacje schematów mogą oszczędzić czas.

Lista rzeczy, których automatyczne aktualizacje nie będą obsługiwane, jest nieskończona, ale niektóre przykłady to migracja danych, dodawanie niepustych kolumn, zmiany nazw kolumn itp.

Musisz także zachować ostrożność w środowiskach klastrowych.

Ale z drugiej strony, jeśli znałbyś wszystkie te rzeczy, nie zadawałbyś tego pytania. Hmm . . OK, jeśli zadajesz to pytanie, powinieneś poczekać, aż będziesz mieć dużo doświadczenia z Hibernacją i automatycznymi aktualizacjami schematu, zanim pomyślisz o użyciu go w prod.


19

Jak wyjaśniłem w tym artykule , nie jest dobrym pomysłem stosowanie hbm2ddl.autow produkcji.

Jedynym sposobem zarządzania schematem bazy danych jest użycie przyrostowych skryptów migracji, ponieważ:

  • skrypty będą znajdować się w VCS wzdłuż twojej bazy kodu. Podczas pobierania gałęzi odtwarzasz cały schemat od zera.
  • skrypty przyrostowe można przetestować na serwerze kontroli jakości przed zastosowaniem ich w środowisku produkcyjnym
  • nie ma potrzeby ręcznej interwencji, ponieważ skrypty mogą być uruchamiane przez Flyway , dlatego zmniejsza możliwość wystąpienia błędu ludzkiego związanego z ręcznym uruchamianiem skryptów.

Nawet Podręcznik użytkownika Hibernacji zaleca unikanie używania tego hbm2ddlnarzędzia w środowiskach produkcyjnych.

wprowadź opis zdjęcia tutaj


To idealna odpowiedź i zgadzam się z nią. Ale naprawdę znajduję pomysł, aby ręcznie utworzyć pierwszy skrypt bazy danych cumbersom (tj. V1_0__initial_script.sql w przypadku przykładu w łączu). Czy istnieje sposób, w jaki mogę utworzyć skrypt z istniejącej bazy danych dewelopera, który Hibernate stworzył dla mnie i zapisać w V1_0_intial_script.sql?
HopeKing

1
Użyj, SchemaExportjak pokazano w tym przypadku testowym .
Vlad Mihalcea

Dzięki. Natknąłem się na zrzut jednego wiersza „mysqldump -u root -p --no-data dbname> schema.sql”. Czy korzystanie z zrzutu generowanego z tego ma jakąś wadę?
HopeKing

1
Nie ma problemu z użyciem zrzutu DB.
Vlad Mihalcea

8

Robimy to w projekcie trwającym od miesięcy i nigdy wcześniej nie mieliśmy problemu. Pamiętaj o 2 składnikach potrzebnych do tego przepisu:

  1. Zaprojektuj model obiektowy przy użyciu podejścia zgodnego z poprzednimi wersjami, czyli nieaktualnych obiektów i atrybutów zamiast ich usuwania / modyfikowania. Oznacza to, że jeśli chcesz zmienić nazwę obiektu lub atrybutu, pozostaw stary bez zmian, dodaj nowy i napisz jakiś skrypt migracyjny. Jeśli musisz zmienić powiązanie między obiektami, jeśli już jesteś w produkcji, oznacza to, że twój projekt był w pierwszej kolejności niewłaściwy, więc spróbuj wymyślić nowy sposób wyrażenia nowej relacji, bez wpływu na stare dane.

  2. Zawsze wykonuj kopię zapasową bazy danych przed wdrożeniem.

Mam wrażenie - po przeczytaniu tego postu - 90% osób biorących udział w tej dyskusji jest przerażonych samą myślą o zastosowaniu takich automatyzacji w środowisku produkcyjnym. Niektórzy rzucają piłkę w DBA. Zastanów się jednak, że nie wszystkie środowiska produkcyjne zapewnią DBA i niewiele zespołów programistów jest w stanie sobie na to pozwolić (przynajmniej w przypadku średnich projektów). Jeśli więc mówimy o drużynach, w których wszyscy muszą robić wszystko, piłka jest na nich.

W takim przypadku, dlaczego nie spróbować po prostu tego, co najlepsze z obu światów? Narzędzia tego typu są tutaj po to, aby pomóc pomocną dłoń, która - dzięki starannemu projektowi i planowi - może pomóc w wielu sytuacjach. I wierzcie mi, administratorzy mogą początkowo być trudni do przekonania, ale jeśli wiedzą, że piłka nie jest w ich rękach, pokochają ją.

Osobiście nigdy nie wrócę do ręcznego pisania skryptów w celu rozszerzenia dowolnego schematu, ale to tylko moja opinia. Po niedawnym przyjęciu baz danych bez schematu NoSQL widzę, że wkrótce wszystkie te operacje oparte na schemacie będą należeć do przeszłości, więc lepiej zacznij zmieniać swoją perspektywę i patrzeć w przyszłość.


4
Nie zgadzam się co do komentarza NoSQL. Zdecydowanie rośnie i ma swoje miejsce, ale istnieje wiele aplikacji, które absolutnie zależą od zgodności ACID dla integralności danych z współbieżnością i transakcjami, których NoSQL po prostu nie jest w stanie zapewnić.
jpswain,

7

Nie zaryzykowałbym tego, ponieważ możesz stracić dane, które powinny były zostać zachowane. hbm2ddl.auto = aktualizacja jest czystym łatwym sposobem na aktualizowanie bazy danych deweloperów.


2
nie tworzysz kopii zapasowych baz danych przed aktualizacją?
Jacob

6
Tak, oczywiście, że tak, ale przywrócenie danych z kopii zapasowej wymaga dużo pracy. Przywracanie kopii zapasowych nie jest kłopotliwe, gdy można również aktualizować bazę danych w uporządkowany sposób.
Jaap Coomans,

6
  • W moim przypadku (Hibernate 3.5.2, Postgresql, Ubuntu) ustawienie hibernate.hbm2ddl.auto=updatespowodowało utworzenie tylko nowych tabel i utworzenie nowych kolumn w już istniejących tabelach.

  • Nie upuszczał tabel, nie upuszczał kolumn ani nie zmieniał kolumn. Można to nazwać bezpieczną opcją, ale coś takiego hibernate.hbm2ddl.auto=create_tables add_columnsbyłoby bardziej jasne.


6

Nie jest to bezpieczne, nie zalecane, ale jest możliwe.

Mam doświadczenie w aplikacji korzystającej z opcji automatycznej aktualizacji w produkcji.

Cóż, główne problemy i zagrożenia znalezione w tym rozwiązaniu to:

  • Wdróż w niewłaściwej bazie danych . Jeśli popełnisz błąd, aby uruchomić serwer aplikacji ze starą wersją aplikacji (EAR / WAR / itp.) W niewłaściwej bazie danych ... Otrzymasz wiele nowych kolumn, tabel, kluczy obcych i błędów. Ten sam problem może wystąpić z prostym błędem w pliku źródła danych (skopiuj / wklej plik i zapomniałeś zmienić bazę danych). Wznowienie sytuacji może być katastrofą w bazie danych.
  • Uruchomienie serwera aplikacji trwa zbyt długo . Dzieje się tak, ponieważ Hibernacja próbuje znaleźć wszystkie utworzone tabele / kolumny / etc przy każdym uruchomieniu aplikacji. Musi wiedzieć, co (tabela, kolumna itp.) Należy utworzyć. Ten problem będzie się nasilał w miarę dorastania tabel bazy danych.
  • Narzędzia baz danych są prawie niemożliwe w użyciu . Aby utworzyć skrypty DDL lub DML bazy danych, które będą działać z nową wersją, musisz pomyśleć o tym, co zostanie utworzone przez automatyczną aktualizację po uruchomieniu serwera aplikacji. Na przykład, jeśli musisz wypełnić nową kolumnę niektórymi danymi, musisz uruchomić serwer aplikacji, zaczekaj, aż Hibernacja utworzy nową kolumnę i uruchom skrypt SQL dopiero po tym. Jak widać, narzędzia do migracji baz danych (takie jak Flyway, Liquibase itp.) Są prawie niemożliwe do użycia z włączoną automatyczną aktualizacją.
  • Zmiany w bazie danych nie są scentralizowane . Dzięki możliwości tworzenia tabel Hibernacji i wszystkim innym trudno jest obserwować zmiany w bazie danych w każdej wersji aplikacji, ponieważ większość z nich jest wykonywana automatycznie.
  • Zachęca do śmieci w bazie danych . Z powodu „łatwego” użycia automatycznej aktualizacji istnieje prawdopodobieństwo, że Twój zespół zaniedba upuszczenia starych kolumn i starych tabel, ponieważ hibernacja automatyczna aktualizacja nie może tego zrobić.
  • Nieuchronna katastrofa . Bezpośrednie ryzyko wystąpienia jakiejś katastrofy w produkcji (jak niektóre osoby wymienione w innych odpowiedziach). Nawet jeśli aplikacja działa i jest aktualizowana przez lata, nie sądzę, że jest to bezpieczny wybór. Przy tej opcji nigdy nie czułem się bezpiecznie.

Dlatego nie zalecam używania automatycznej aktualizacji w produkcji.

Jeśli naprawdę chcesz korzystać z automatycznej aktualizacji w produkcji, polecam:

  • Oddzielne sieci . Środowisko testowe nie może uzyskać dostępu do środowiska homologacji. Pomaga to zapobiec wdrożeniu, które miało być w środowisku testowym, zmienić bazę danych homologacji.
  • Zarządzaj kolejnością skryptów . Musisz zorganizować skrypty, aby działały przed wdrożeniem (zmiana tabeli struktury, upuść tabelę / kolumny) i skrypt po wdrożeniu (wypełnij informacje o nowych kolumnach / tabelach).

I w przeciwieństwie do innych postów, nie sądzę, aby włączona była automatyczna aktualizacja, która jest związana z „bardzo dobrze płatnymi” DBA (jak wspomniano w innych postach). DBA mają ważniejsze rzeczy do zrobienia niż pisanie instrukcji SQL w celu tworzenia / zmiany / usuwania tabel i kolumn. Te proste codzienne zadania mogą być wykonywane i automatyzowane przez programistów i przekazywane do oceny przez zespół DBA, nie wymagając od Hibernate i DBA „bardzo dobrze płatnych”, aby je napisać.


4

Nie, nigdy tego nie rób. Hibernacja nie obsługuje migracji danych. Tak, sprawi, że twój schemat będzie wyglądał poprawnie, ale nie zapewni, że cenne dane produkcyjne nie zostaną utracone w procesie.


4
  • Zazwyczaj aplikacje korporacyjne w dużych organizacjach działają ze zmniejszonymi uprawnieniami.

  • Nazwa użytkownika bazy danych może nie mieć DDLuprawnień do dodawania hbm2ddl.auto=updatewymaganych kolumn .


to problem, z którym często się spotykam. Próbujemy użyć hibernacji do początkowego utworzenia bazy danych, ale często nie jest to możliwe.
Dan

5
To nie jest „problem”, to słuszna sprawa.
Vladimir Dyuzhev,

2

Zgadzam się z Vladimirem. Administratorzy w mojej firmie na pewno nie doceniliby tego, gdybym nawet zaproponował taki kurs.

Co więcej, utworzenie skryptu SQL zamiast ślepego zaufania Hibernacji daje możliwość usunięcia pól, które nie są już używane. Hibernacja tego nie robi.

Uważam, że porównanie schematu produkcyjnego z nowym schematem daje jeszcze lepszy wgląd w zmiany dokonane w modelu danych. Wiesz oczywiście, ponieważ to zrobiłeś, ale teraz widzisz wszystkie zmiany za jednym razem. Nawet te, które sprawiają, że lubisz „Co do cholery ?!”.

Istnieją narzędzia, które mogą tworzyć dla ciebie deltę schematu, więc nie jest to nawet ciężka praca. I wtedy dokładnie wiesz, co się stanie.


„Istnieją narzędzia, które mogą stworzyć dla ciebie deltę schematu”: Czy możesz wskazać niektóre z takich narzędzi?
Daniel Cassidy

Myślę, że apexsql.com/sql_tools_diff.asp to robi i prawdopodobnie więcej aplikacji. Zwykle robię to ręcznie, zrzucając schemat i różnicując (używając diff).
extraneon

2

Schemat aplikacji może ewoluować w czasie; jeśli masz kilka instalacji, które mogą być w różnych wersjach, powinieneś mieć sposób, aby upewnić się, że twoja aplikacja, jakieś narzędzie lub skrypt jest w stanie migrować schemat i dane z jednej wersji krokowo do dowolnej następnej.

Posiadanie całej swojej trwałości w mapowaniach hibernacji (lub adnotacjach) jest bardzo dobrym sposobem na kontrolowanie ewolucji schematu.

Należy wziąć pod uwagę, że ewolucja schematu obejmuje kilka aspektów:

  1. ewolucja schematu bazy danych w dodawaniu kolejnych kolumn i tabel

  2. usuwanie starych kolumn, tabel i relacji

  3. wypełnianie nowych kolumn wartościami domyślnymi

Narzędzia hibernacji są szczególnie ważne w przypadku, gdy (jak z mojego doświadczenia) masz różne wersje tej samej aplikacji w wielu różnych bazach danych.

Punkt 3 jest bardzo wrażliwy w przypadku korzystania z Hibernacji, tak jak w przypadku wprowadzenia nowej właściwości o wartości logicznej lub wartości numerycznej, jeśli Hibernacja znajdzie w takich kolumnach wartość zerową, jeśli podniesie wyjątek.

Chciałbym więc: rzeczywiście użyć zdolności Hibernacji do aktualizacji schematu, ale oprócz tego trzeba dodać wywołanie zwrotne związane z obsługą danych i schematu, na przykład w celu wypełnienia wartości domyślnych, usunięcia nieużywanych kolumn i tym podobnych. W ten sposób zyskujesz zalety (skrypty aktualizacji schematu niezależne od bazy danych i unikanie powielania kodowania aktualizacji, w perystencji i skryptach), ale obejmuje również wszystkie aspekty operacji.

Na przykład, jeśli aktualizacja wersji polega po prostu na dodaniu właściwości o wartości varchar (stąd kolumna), która może domyślnie mieć wartość NULL, z automatyczną aktualizacją będziesz gotowy. Tam, gdzie konieczna jest większa złożoność, konieczne będą dalsze prace.

Zakłada się, że po aktualizacji aplikacja może zaktualizować swój schemat (można to zrobić), co oznacza również, że musi mieć uprawnienia użytkownika do wykonania tego schematu. Jeśli polityka klienta temu zapobiegnie (prawdopodobnie sprawa Lizard Brain), będziesz musiał dostarczyć skrypty specyficzne dla bazy danych.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.