Bezpieczny sposób na wygenerowanie unikalnego identyfikatora na potrzeby mysql

0

Witam Was,

Myślę jak najrozsądniej wygenerować jakąś unikalny ciąg znaków. Pomyślałem że zrobię tak program odczyta np nr seryjny płyty głównej i zakoduje go w md5. Ale szybko zauważyłem że do nr seryjnego muszę dodać coś jeszcze bo odpalone 2 instancje tego samego programu na jednym komputerze dadzą ten sam identyfikator (md5). Nie chcę blokować aby było można odpalić tylko 1 kopię. Tak się zastanawiam co najrozsądniej dodać do odczytanego nr seryjnego. Może aktualny czas? Jest to nie możliwe aby w tej samej milisekundzie włączyły się obie kopie programu.

Ponieważ zapytacie po co mi to więc postanowiłem trochę połączyć posty.

Muszę zablokować kilka rekordów w bazie mysql gdzie np operacje w danej tabeli będą wykonywane przez wątki w programie a połączenie z bazą będzie przez ten sam login i hasło.

1

jak masz InnoDB to użyj wg mnie transakcji w wątkach. Zadbaj tylko aby co jakiś czas czyścić bazę z nieukończonych transakcji bo jednak praca na wątkach potrafi pozostawić po sobie trochę śmieci.

0

@robertz68: Też tak początkowo myślałem ale takie np SELECT ..... FOR UPDATE w transakcji faktycznie blokuje wiersz przed odczytem ale jeżeli teraz użytkownik programu kliknie np "odczytaj dokument xyz" to program się zwiesi bo będzie czekał tak długo aż zakończy się transakcja (SELECT ..... FOR UPDATE), no chyba że można jakoś sprawdzić czy dany wiersz jest zablokowany lub nie.

3

Nie rozumiem, co próbujesz osiągnąć; najpierw mówisz, że chcesz zablokować jakieś wiersze, a potem narzekasz, że "program się zwiesi przy odczycie tych wierszy"; albo blokujesz, albo nie blokujesz - nie da się bezpiecznie osiągnać stanu pomiędzy.

1

Po pierwsze, operacje trwające długo i blokujące tabele lub jej część można uznać za serwisowe i należy je wykonywać w czasie nieużywania aplikacji lub gdy jest małe wykorzystanie bazy danych, nie wiem, np. 5 rano.
W sytuacji gdy dane są blokowane na krótko, np. w czasie normalnego używania programu nie jest to aż tak wielkim problemem bo po to jest timeout który potrafi chwilę poczekać na dostęp do danych.
Jeśli już naprawdę musisz "synchronizować" dane między tabelami czy tam bazami w szczycie używania bo chyba po to te polecenie to albo rób to partami albo np. użyj mocniejszej technologii bazy danych jeśli to możliwe (oracle, microsoft) i zainteresuj się replikacjami.
W każdym razie w niedużych zastosowaniach problem blokowania rekordów jest pomijalny, przy dużych systemach jest to poważny problem ale są do tego mechanizmy w zaawansowanych silnikach oraz reguły których trzeba się trzymać. Jednakże to jest poważna wiedza i raczej na żadnym forum jej nie poznasz.
Oznaczenie rekordu jako zablokowanego jest ok ale wg mnie tylko do potrzeb informacyjnych, w stylu nie poprawiaj tego dokumentu bo używa go ta czy tamta osoba.
Takie oznaczenia najczęściej kończą się tym że później znacznik ten nie jest zdejmowany z rekordu bo coś tam się nie zakończyło i zaczynają się problemy. Trzeba to czyścić itp.
Poza tym operacje update nie są bardzo szybkie, jak będziesz co chwilę oznaczał rekord jako zablokowany i po chwili zdejmował tą informację z rekordu to wg. mnie wydłużysz operację minimum dwukrotnie.

Jeśli już koniecznie chcesz tak zrobić to:

  1. na starcie pobierz nazwę stanowiska albo IP komputera,
  2. każdy start wątku oznacz czasem z funkcji GetTickCount (nigdy nie będzie taka sama wartość).

To cię zabezpieczy przed takimi samymi danymi na różnych komputerach a nawet na tym samym.

BTW wołaj @wloochacz bo chyba nie ma na tym forum lepszego z baz danych

1

w mssql jest NOLOCK, które pozwala odczytać zablokowane przez transakcję rekordy, w mysql też można osiągnąć taki efekt: https://stackoverflow.com/questions/917640/any-way-to-select-without-causing-locking-in-mysql

0

@robertz68: "Oznaczenie rekordu jako zablokowanego jest ok ale wg mnie tylko do potrzeb informacyjnych, w stylu nie poprawiaj tego dokumentu bo używa go ta czy tamta osoba."

Tak mam zrobione przy istotniejszych "dokumentach" kolumna z identyfikatorem+czas np 1 minuta: Ktoś inny próbuje zmienić dokument wiec zablokuj/poinformuj go przed edycją do czasu timeout chyba że o ta osoba(program) znowu zwiększy timeout o kolejną np minutę. Bo np pani Kwiatkowska otwarła dokument zaczęła go edytować i zamiast zapisać poszła na kawkę :) A kaziu czeka bo też coś chciał w nim zmienić.

@robertz68: SELECT ... FOR UPDATE stosuję bardzo rzadko, pÓÓÓÓki co to tylko do np numeracji dokumentów aby się nie powtórzyły 2 dokumenty o takim samym numerze.

Masz taką sytuację: Przychodzi 10 pracowników do firmy odpalają kompa i każdy klika pobierz zamówienia z Alledrogo i dodaj je do realizacji ( wątki robią to automatycznie ) ( bo nie wie czy kolega obok to zrobił a aplikacja nie jest trójwarstwowa). To chyba takie rozwiązanie jak powyżej jest najrozsądniejsze aby nie blokować całej tabeli lub wykonywać select for update.

0
Rafał D napisał(a):

Bo np pani Kwiatkowska otwarła dokument zaczęła go edytować i zamiast zapisać poszła na kawkę :) A kaziu czeka bo też coś chciał w nim zmienić.

Jak ja nienawidzę takiego postępowania ale prawie nic na to nie można poradzić.
W takiej sytuacji robię zazwyczaj tak:

  • informuję kto blokuje dokument,
  • wyświetlam go w trybie tylko do odczytu.

To rozwiązuje sprawę prawie zawsze. Teraz jest troszkę większy problem bo niektórzy pracownicy są na pracy zdalnej i ciężej się z nimi porozumieć, ale jednak załatwia to sprawę.
Zadbaj tylko o to żeby "właściciel" zmian miał możliwość zwolnić blokadę. Nie bierz tego na siebie bo będą ci dupę truli żebyś odblokował dokument. Oczywiście zostaw sobie taką możliwość w kodzie programu bo jednak może okazać się że prezes blokuje dokument a jest na spotkaniu i wtedy ty wkroczysz "cały na biało" i usuniesz blokadę :).

Co do twojego sposobu na pobieranie zamówień. Ja jednak zrobiłbym to inaczej. Na formie programu zrobiłbym miejsce na coś w stylu schedulera w którym wyświetlałbym nagłówki oczekujących zamówień. Po pobraniu przez któregoś z pracowników (ręcznie) dokumentu znikałby on z tej listy. Od tego w końcu są pracownicy. Sposoby odświeżania tej listy zostawiam tobie, można przez bazę, można w inny sposób.

0

żeby sprawdzić czy ktoś blokuje bez czekania trzeba dodać nowait do zapytania - select * from * for update nowait

0

Masz taką sytuację: Przychodzi 10 pracowników do firmy odpalają kompa i każdy klika pobierz zamówienia z Alledrogo i dodaj je do realizacji ( wątki robią to automatycznie ) ( bo nie wie czy kolega obok to zrobił a aplikacja nie jest trójwarstwowa). To chyba takie rozwiązanie jak powyżej jest najrozsądniejsze aby nie blokować całej tabeli lub wykonywać select for update.

To robię index unikalny z pole identyfikującym zamówienie (mam na myśli identyfikator z allegro) po stronie aplikacji pozostaje obsługa powielonego indeksu

0
Rafał D napisał(a):

Myślę jak najrozsądniej wygenerować jakąś unikalny ciąg znaków.

GUID-a generuj i konwertuj na ciąg znaków — są do tego wbudowane funkcje.

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