Oracle On delete cascade czy to dobre podejście

0

Siemka,

Od razu zaznaczę że jeśli uznacie, że temat bardziej pasuje do działu Bazy danych to feel free i przenieście.

Krótka piłka - czy ON DELETE CASCADE w bazie danych (w moim przypadku akurat Oracle) jest dobrą praktyką czy nie? Czy może jednak "czyściej" jest usuwać ręcznie łańcuszek powiązanych ze sobą encji, w Javie?

@Shalom @jarekr000000 ?

6

DROP DATABASE / DROP SCHEMA - usuwa szybciej i skuteczniej.

1

W przypadku ogólny jest to złą praktyka. W przydatku szczególnym jest ok i nic do tego nie ma java.

3

Nie ma na to jednoznacznej odpowiedzi. Jak dla mnie zasada jest taka - jeśli to są dane pomocnicze lub pierdoły, wtedy ON DELETE CASCADE. Przykładem mogą być wszelkie pivoty i większość relacji 1:1. Jeśli to są wartościowe dane, np. posty na forum*, wtedy można przez pomyłkę je wyrzucić, czyli nie-e.

  • Mam na myśli inne forum.
5

Zależy od kontekstu, ale co do zasady jestem przeciwnikiem.

  1. Brak kontroli od strony aplikacji. Możesz operować w pamięci na danych, które zostały usunięte przez silnik bazy danych. Możesz też usunąć za dużo.
  2. Rzadko kiedy fizycznie usuwa się dane - raczej zmienia się ich "stan" lub przenosi się je do "archiwum".
0

Jeśli logika aplikacji byłaby skoncentrowana po stronie bazy danych, to może użyłbym tego. Ale skoro jest o Javie, to zakładam, że tam jest głównie ta logika, i wtedy lepiej czegoś takiego nie robić. Po prostu będzie mniej miejsc do patrzenia, żeby zorientować się jak coś działa. Poza tym w JPA jest dostępny analogiczny mechanizm i można się też zastanawiać, czy jego nie użyć.

2

Odpowiem bazując sytuacji z przed kilku lat:
Duża baza danych rozwijana przez wiele zespołów. Masz aplikację główną, która operuje na tabeli klienci oraz konta_bankowe. Klient zadzwonił i poprosił o możliwość zdefiniowania konta_bankowego z towarem (bo np sprzedaje wyroby koncesjonowane, które muszą wpływać na inne konto bankowe) w aplikacji webowej (główna jest desktopowa). Opcje są dwie. Do tabeli konto_bankowe dodajesz IDTowaru (i rozwalasz większość raportów i zapytań, które operują na tej tabeli bo nagle select nr_konta into vkonto from konta_bankowe where klient_id = :idklienta wywalui too_many_rows w przypadku oracle) lub dodajesz nową tabelę spinającą idkonta_bankowego z id_towaru. Programista, który tworzy modyfikację pracuje od niedawna bo to prosty temat więc towrzy tabelę i funkcję odpowiednio je uzupełniające (tzw DBInterface). Po pół roku klient rozwiązuje współpracę i powołując się na RODO mówi usuńcie moje dane z bazy. Ma do tego prawo więc analityk dostaje za zadanie zrób delete from klienci where idklienta = xxx. W takim wypadku on delete cascade załatwia temat wszystkich takich "niektrolowanych" przyrostów bazodanowych i sprzątanie śmieci.

Inaczej sytuacja ma się gdy np potrzebujesz takie dane zostawić do statystyk lub gdy są np potrzebne innemu programowi (np płacowemu) wtedy mimo iż główny rekord usuwasz to chcesz aby statystyki pozostały. Nie ma jednej odpowiedzi tak jak nie ma jednego dobrego rozwiązania optymalizacyjnego do każdego selecta.

3

@Pinek: ale tak serio -
w apkach biznesowych, jeśli już wszystko poszło nie tak i mam SQL bazę danych i do tego jeszcze trzymam w niej dane (olaboga! ). To wtedy na pewno nie robię ON CASCADE DELETE.
Bo w ogóle nigdy nie robie żadnego DELETE.
Jeśli już to DELETE są zrobione w jakiś batchach usuwających stare dane - po roku.
Powiem więcej - UPDATE też w zasadzie nie robię...`
(Widze, że @Charles_Ray to zasugerował. Nie używanie DELETE to lekcja z jeszcze pierwszego januszsoftu - 20 lat temu).

1

@woolfik: a teraz wyobraź sobie sytuacje ze właśnie ktoś z boku robi niewinnego deleta na bazie i usuwa automatycznie jakieś istotne dane, co do których jest obowiązek trzymania na jakiś czas. Dziwne jest to podejście, że ktoś robi jednego delete i ma „pewność” ze wszystko zostanie posprzątane - powinien być do tego zaimplementowany dedykowany proces biznesowy.

1

Odpowiedź jest zależna od projektu bazy danych. We wspomnianym forum to zła praktyka. Powiedzmy, że ktoś napisał dużo postów przez kilka lat i usuwa konto. Nie dość, że razem z użytkownikiem zniknęłyby wartościowe posty, to jeszcze kilka deletów mogłoby spowodować spore zużycie procesora. Co innego dodać kontrolkę w panelu admina, która usunie posty użytkownika, którego może już nawet nie być. Poza tym wtedy można rozłożyć pracę na bazie na mniejsze części, żeby forum się nie zatkało.
Lepiej by to wyszło w przypadku serwera plików - cascade wraz z folderem usuwa podfoldery i pliki. Wszystkie one są widoczne tylko dla właściciela, więc obciążenie nie jest tak duże - zwyczajnie część użytkowników może być na jednym klastrze a część na innym. Chociaż to też dałoby się zrobić inaczej.
Tak, że problem nie leży w samym mechanizmie bazy a w tym jak baza jest zaprojektowana.

3

Najpierw trzeba zasięgnąć opinii księgowego, prawnika czy dane w ogóle mogą zostać trwale usunięta i po jakim okresie czasu.

2

Może jakiś szczególny przypadek by uszedł, ale w ogólności bałbym się tak zrobić.

Nawet z pozoru niewinne dodanie czegoś do tabelki i usunięcie może doprowadzić do problemów. Jeśli masz do takiej tabeli FK, to baza musi sobie sprawdzić na tabeli "child" czy ma rekordy powiązane z usuwanym. Nie zawsze jest w stanie to zrobić po indeksie, więc może robić full scana na takiej tabeli, a jeśli tabel "child" jest dużo, to masz odpowiednio więcej full scanów. W ten sposób I/O, które normalnie idzie na obsługę requestów generowanych przez aplikację, jest przejadane przez operację "delete" niewinnego rekordu.
Nie dzieje się tak zawsze, ale zanim zrobisz delete na bazie, to się dobrze zastanów czy jest potrzebny i jakie mogą być implikacje takie projektu po X czasu (np. ktoś podpina trigger ON DELETE, ktoś tworzy nową tabelką i dodaje FK do Twojej i nie ma pojęcia o ON DELETE CASCADE :))

Oracle ma np. global temporary tables, które po commicie potrafi zapomnieć o zawartości, albo tylko trzymać dane w czasie trwania połączenia bazodanowego.
Inne silniki pewnie mają coś podobnego. Usuwanie historii możesz ogarnąć partycjonowaniem/sub-partycjonowaniem.

0

A może by tak wgl nie kasować danych z bazy (każde delete jest potencjalnie niebezpieczne) tylko np zmieniać jakąś flage w rekordzie która oznacza "usunięcie" (najlepiej jeszcze z datą i czasem edycji)

0

Może dodam faktycznie trochę więcej szczegółów co do mojego przypadku - nie chodzi mi o usuwanie jakichś ważnych rzeczy jak danych klientów, faktur itp itd. W moim przypadku, pozwalam użytkownikom na tworzenie szablonu prezentacji. No i taka prezentacja ma w sobie jakieś pola czyli szablon, który potem zostanie wypełniony już poważnymi i sensownymi danymi. Więc moje tabelki operują raczej na "metadanych".

Czyli jak usuwam dany szablon, to chcę również usunąć te pola z szablonu - a one są zapisane w osobnych tabelkach. Stąd też mam dylemat bo to jednak nie są sensitive data.

2

pozwalam użytkownikom na tworzenie szablonu prezentacji - ale serio takie rzeczy w SQL?
Toż to brzmi jak straszna udręka, zaraza i armagiedon.

1

Nie robiła bym delete w ogóle. Raczej archiwizacja, anonimizowanie. Natomiast kaskadowe delete może Ci wysypać część danych które są potrzebne gdzieś indziej, obojętnie gdzie. Pamiętaj że delete w bazach mimo wszystko nie obniża wskaźnika wysokiej wody stąd może kiedyś się okazać że baza zajmuje mnóstwo miejsca, a danych w niej niewiele. Albo co gorsza brakuje danych które są potrzebne do zestawień chociażby dla KNF/PIU/RIO czy czegokolwiek innego co może dzisiaj jeszcze nie istnieje a za rok może mieć prawo do kontrolowania instytucji.

0
kate87 napisał(a):

Nie robiła bym delete w ogóle. Raczej archiwizacja, anonimizowanie.

To nie leży w obszarze dobrych/złych praktyk albo w ogóle jakichkolwiek praktyk.
To po prostu zależy od danego projektu; to co ja robię, zanonimizowanie danych nie ma sensu, soft-delete (czyli flaga na wierszu usunięte sensu też nie ma, bo to jest usuwane ma być usunięte i tyle) również nie ma, ponieważ usuwane dane są niepotrzebne.
A jeżeli już są usuwane, to jest to usuwane ze wszystkimi podległymi zależnościami.
Oczywiście jeżeli istnieje jakaś zależność, która blokuje możliwość usuwania - to takich danych usunąć się nie da (z punktu widzenia danego procesu biznesowego, a nie bazy danych sensu stricte).

Natomiast kaskadowe delete może Ci wysypać część danych które są potrzebne gdzieś indziej, obojętnie gdzie.

To jest delikatnie powiem, bzdura.
Jeżeli baza jest poprawnie zaprojektowana to nic takiego się nie wydarzy, bo klucze obce będą trzymały takie pomysły za pysk i pozwolić się nie usuną.
Zadaniem kluczy obcych i ogólnie wszelkich constraints w bazie danych jest utrzymanie danych w odpowiedniej jakości.
Żadnych lewych wpisów, żadnych osieroconych wierszy. A więc chodzi właśnie o to, żeby nic się absolutnie nie posypało.

Pamiętaj że delete w bazach mimo wszystko nie obniża wskaźnika wysokiej wody stąd może kiedyś się okazać że baza zajmuje mnóstwo miejsca, a danych w niej niewiele. Albo co gorsza brakuje danych które są potrzebne do zestawień chociażby dla KNF/PIU/RIO czy czegokolwiek innego co może dzisiaj jeszcze nie istnieje a za rok może mieć prawo do kontrolowania instytucji.

Proszę Cię, co to za teza jest w ogóle?
Jeżeli ktoś chce usuwać dane i to jeszcze kaskadowo, to zakładam że wie co robi i wie co usuwa i dlaczego można to w ogóle usunąć.
Przecież kaskadowe usuwanie czy aktualizacja **nie jest **globalnym założeniem - to się bardzo precyzyjnie definiuje gdzie ma działać i jak ma działać.
Ale tłumaczenie tego w sposób "to złe jest, nie rób tego, bo usuniesz dane" jest z lekka bez sensu.

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