Jedna transakcja shared a wielowątkowość

Jedna transakcja shared a wielowątkowość
AS
  • Rejestracja:około 4 lata
  • Ostatnio:3 dni
  • Postów:19
0

Cześć mam pytanko, nie wiem jak do tego podejść ale.

screenshot-20240204115107.png

Zdjęcie jak ma to wyglądać 😄 Mamy 2 tabelki z danymi (A i B)
Potrzebuje zrobić "snapshot" danych, dane A pozwolą mi stworzyć dane B (prawa strona) oraz muszą być zapisane do innej tabelki A (przekopiowane z A lewo do A prawo).
C tabelka również ma być przekopiowana.

Chciałbym to zrobić równolegle tylko problem pojawia się podczas współdzielenia transakcji.
Bo nie może istnieć sytuacja taka, że proces A się wykona (czyli zapisze do A i B) a C nie wykona się bo będzie jakiś error.
Jak wyczytałem z użyciem metody Transactional on tworzy sobie za każdym razem nową transkacje, jak próbowałem dawać parametr Mandatory (w pod metodzie) to dostawałem błąd że transakcja nie istnieje co by się zgadzało z opisem że nie jest dzielona.

Czy ktoś mógłby jakoś doradzić jak/czym albo jak sobie z tym poradzić ?

(Próbowałem to z użyciem CompletableFuture)

Dzięki za każdą poradę 😉

AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 dni
  • Postów:3561
0

Brzmi to jak javowsko-springowy YX problem

@Transacinal to pole minowe
A pachnąca tu między wierszami rozproszona transakcja to nie mniejszy problem.


Bo C to najlepszy język, każdy uczeń ci to powie
RequiredNickname
tylko w przeciwieństwie do transakcji rozproszonych tego drugiego problemu z wszechobecnym jpa nie unikniemy w korpo projektach :(
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 5 godzin
  • Postów:2367
0

Chciałbym to zrobić równolegle tylko problem pojawia się podczas współdzielenia transakcji.

Dlaczego równolegle? Co zyskujesz kosztem złożoności rozwiązania?

Poprawnie byłoby zbudować logikę, które obsługuje wykonanie Twojego workflow i mieć mechanizm, który jest w stanie wyszukać instancje workflow, które padły i wznowić ich wykonanie.
Zamiast

Kopiuj
activity1.execute();
activity2.execute();

coś w stylu

Kopiuj
MyBusinessProcess process = MyBusinessProcess(activity1,activity2);
process.execute();

Gdzie ten MyBusinessProcess zamyka maszyną stanową/workflowem, który jest w stanie "kontynuować wykonanie procesu zgodnie z logiką, której potrzebujesz" (trzeba to sobie oprogramować, można wykorzystać istniejące frameworki).

Kolejna sprawa, to piszesz, że równolegle... ale co z przeplotami wykonania? Piszesz o abstrakcyjnych tabelach A,B,C, ale gdyby C nie było w jakiś sposób związane z przetwarzaniem A,B to chyba problemu by nie było? Czy robi Ci różnicę kolejność w jakiej zadania rozpoczną pracę i w jakiej zakończą pracę i jaki będzie stan (zawartość) tabel A,B,C w określonym punkcie czasu?

np. możesz mieć takie przeploty (| - momenty rozpoczęcia/zakończenie zadania, - - wykonanie zadania)

Kopiuj
Task #1: |------------------------|
Task #2: |------------------------|

Task #1: |------------------------|
Task #2:    |---------------------|

Task #1: |------------------------|
Task #2:    |-------------------|
...

Przeplot#1 - Task#1 i #2 zaczynają i kończą się dokładnie w tym samym czasie (mało prawdopodobne ale mocno zależne od tego "jak i gdzie mierzymy czas")
Przeplot#2 - Task#1 zaczyna się wcześniej niż 2, ale kończą w tym samym momencie
Przeplot#3 - Task#2 zaczyna się później niż task#1, ale kończy wcześniej niż Task#1
...

edytowany 1x, ostatnio: yarel
AS
  • Rejestracja:około 4 lata
  • Ostatnio:3 dni
  • Postów:19
0
yarel napisał(a):

Chciałbym to zrobić równolegle tylko problem pojawia się podczas współdzielenia transakcji.

Dlaczego równolegle? Co zyskujesz kosztem złożoności rozwiązania?

Poprawnie byłoby zbudować logikę, które obsługuje wykonanie Twojego workflow i mieć mechanizm, który jest w stanie wyszukać instancje workflow, które padły i wznowić ich wykonanie.
Zamiast

Kopiuj
activity1.execute();
activity2.execute();

coś w stylu

Kopiuj
MyBusinessProcess process = MyBusinessProcess(activity1,activity2);
process.execute();

Gdzie ten MyBusinessProcess zamyka maszyną stanową/workflowem, który jest w stanie "kontynuować wykonanie procesu zgodnie z logiką, której potrzebujesz" (trzeba to sobie oprogramować, można wykorzystać istniejące frameworki).

Kolejna sprawa, to piszesz, że równolegle... ale co z przeplotami wykonania? Piszesz o abstrakcyjnych tabelach A,B,C, ale gdyby C nie było w jakiś sposób związane z przetwarzaniem A,B to chyba problemu by nie było? Czy robi Ci różnicę kolejność w jakiej zadania rozpoczną pracę i w jakiej zakończą pracę i jaki będzie stan (zawartość) tabel A,B,C w określonym punkcie czasu?

np. możesz mieć takie przeploty (| - momenty rozpoczęcia/zakończenie zadania, - - wykonanie zadania)

Kopiuj
Task #1: |------------------------|
Task #2: |------------------------|

Task #1: |------------------------|
Task #2:    |---------------------|

Task #1: |------------------------|
Task #2:    |-------------------|
...

Przeplot#1 - Task#1 i #2 zaczynają i kończą się dokładnie w tym samym czasie (mało prawdopodobne ale mocno zależne od tego "jak i gdzie mierzymy czas")
Przeplot#2 - Task#1 zaczyna się wcześniej niż 2, ale kończą w tym samym momencie
Przeplot#3 - Task#2 zaczyna się później niż task#1, ale kończy wcześniej niż Task#1
...

"Dlaczego równolegle? Co zyskujesz kosztem złożoności rozwiązania? "

Tylko po to żeby przyspieszyć proces.

"(trzeba to sobie oprogramować, można wykorzystać istniejące frameworki). "

Masz jakieś fajne na myśli ? Mi z tego co kojarzę jest Spring Batch tylko nie wiem czy to nie jest armata do muchy.

"> Kolejna sprawa, to piszesz, że równolegle... ale co z przeplotami wykonania? Piszesz o abstrakcyjnych tabelach A,B,C, ale gdyby C nie było w jakiś sposób związane z przetwarzaniem A,B to chyba problemu by nie było? Czy robi Ci różnicę kolejność w jakiej zadania rozpoczną pracę i w jakiej zakończą pracę i jaki będzie stan (zawartość) tabel A,B,C w określonym punkcie czasu?"

C jako tako nie jest powiązane z A i B w sensie jeśli chodzi o kalkulacje czy coś natomiast nie może być takiej sytuacji że A i B się przekalkuluje a C wyskoczy gdzieś error i nie przekopiuje.
C również może się zacząć później i skończyć wcześniej nie ma to wpływu.

Przez to myślałem nad jakąś transakcją ale może dobrym pomysłem by było "ala proces" to ogarnąć.

edytowany 1x, ostatnio: ArturoS159
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:3 miesiące
  • Postów:2787
2

Dla mnie też brzmi jak XY problem.

W świecie Springowym zazwyczaj:

  • @Transactional na metodzie
  • @Async na metodzie
  • @Version nad polem encji

i zazwyczaj działa xD

YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 5 godzin
  • Postów:2367
1
ArturoS159 napisał(a):

...

"Dlaczego równolegle? Co zyskujesz kosztem złożoności rozwiązania? "

Tylko po to żeby przyspieszyć proces.

Czy sekwencyjnie jest zbyt wolno? O ile będzie szybciej ?

"(trzeba to sobie oprogramować, można wykorzystać istniejące frameworki). "

Masz jakieś fajne na myśli ? Mi z tego co kojarzę jest Spring Batch tylko nie wiem czy to nie jest armata do muchy.

Szukaj pod hasłami: Java FSM, Spring FSM, z bardziej złożonych rozwiązań: Flowable, Activiti, Camunda. Ale to musisz mieć dobry powód do takiej złożoności.

W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:38 minut
  • Postów:3540
0

Podstawowe pytanie - czy to jest w obrębie jednej bazy danych czy więcej niż jednej.

  1. Jeśli to w obrębie jednej bazy danych, a baza ma taką opcję to zcedowałbym kopiowanie do bazy danych - i transakcje trzymał właśnie tam. W ostatecznym rozrachunku takie zabawy na zbiorach w bazie danych są najprostsze właśnie na bazie danych.
  2. W przypadku gdy kopiujesz z bazy do bazy i nie masz aż tak wielu danych to wystarczy użyć executora:
Kopiuj
@Service
public class SynchronizationService {
  private final SourceRepository source;
  private final TargetRepository target;
  private final ConcurrentTaskExecutor executor;

  // konstruktor

  @Transactional
  public void synchronize() {
    // zadziała, jeśli storeTableA i storeTableC będą też oznaczone @Transactional
    CompletableFuture.allOf(
      executor.submit(() -> source.getTableA()).andThenAccept(list -> target.storeTableA(list)),
      executor.submit(() -> source.getTableC()).andThenAccept(list -> target.storeTableC(list))
    ).join();
  }
}

  1. W końcu - jeśli masz dużo danych to dobrze użyć batch processingu.
Zobacz pozostałe 3 komentarze
99xmarcin
O Ile rollback to kwestia wysłania do bazy rollback tx to należy zakładać że każdy może wysłać co zwinie transakcje na DB, oraz że wszystkie pozostałe operacje zaczną rzucać wyjątki...
YA
Moim zdaniem, gdyby Spring magicznie propagował kontekst transakcyjny do ConcurrentTaskExecutora, to można by zapomnieć o ACID ;-) Nawet o eventual consistency. Może trzeba by ukuć nowy termin: phantom consistency
99xmarcin
ACID jest na bazie i cały czas by obowiązywał (zakładam że sync musi być na najniższym poziomie czyli faktycznego połączenia do bazy). Jedyne co byśmy stracili to kolejność wysyłania instrukcji na poziomie programu. To że można zwracać Future z repo sugeruje że się da, ale jak już wspomniałem nie piszę w springu od wielu lat: https://wesome.org/spring-data-jpa-async-query-results
W0
Spokojnie, to nie zadziała :D Chciałem technikalia zachować na weekend. Wrzuciłem to tutaj plbo kiedyś pracowałem w projekcie, gdzie była customowa ThreadFactory przekazywana do TaskExecutora i ona była "mądra". Nie było to stuprocentowo bullet-proof (tzn. nie można tego skopiować do innego projektu i oczekiwać, że będzie działało), ale działało bardzo dobrze w limitowanym scopie.
YA
Wydaje mi się, że taki transaction context musiałby być skojarzony z konkretnym taskiem, a nie pulą/wątkami. Możliwe że spring ma jakieś task decoratory. W każdym razie kod sobie zapisałem, bo to dobry materiał na zadawanie pytań na interview :)
AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 dni
  • Postów:3561
0
wartek01 napisał(a):

... są najprostsze właśnie na bazie danych.

Dlaczego sposób podania tematu mi się kojarzy z Excellem ?

ArturoS159 napisał(a):

Potrzebuje zrobić "snapshot" danych,

ArturoS159 napisał(a):

"Dlaczego równolegle? Co zyskujesz kosztem złożoności rozwiązania? "

Tylko po to żeby przyspieszyć proces.

No tak, snapshoty z bazy są znanym sposobem polepszenie wydajności
Integralności zresztą też ;)


Bo C to najlepszy język, każdy uczeń ci to powie
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 5 godzin
  • Postów:2367
1

@wartek01 nie żebym się czepiał, ale może czegoś nie rozumiem z magii springowej (tzn. na pewno nie rozumiem :-)), ale jeśli chodzi Twój przykład, to tam masz 3xTransactional:

  • Transactional-1 na wątku głównym (z którego wołasz synchronize())
  • Transactional2-3 na wątkach executora

Każdy taki transactional działa w ramach kontekstu transakcyjnego, który w springu jest utrzymywany per wątek (i domyślnie, w ramach tego samego wątku jest propagowany na kolejne metody oznaczone Transactional). Masz więc 3 transakcje (jedna na wątku głównym) i te 2 z executora. Jak storetTableA przejdzie, a storeTableC się wywali, to chyba nie będzie stanu o jaki autorowi posta chodzi.

Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
0

Masz dwa niezależne procesy do ogarnięcia.

  • wyliczanie B na podstawie A oraz zapisanie kopii A z których wyliczono B.
  • kopiowanie C.

To wszystko chcesz uruchomić w ramach jednej transakcji, a raczej chcesz to uruchomić na raz.

Użyj Spring Batch, to jest bardzo proste i lekkie rozwiązanie. w którym musisz ogarnąć jedynie konfigurację zadań. Cała reszta „zrobi się sama”.

Job 1 – kopiowanie danych w C
Job 2 – trzystopniowy, czyli pobranie A, i dwa równoległe kroki wyliczanie B, zapisywanie A`.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)