Tworzenie dodatkowego klucza podstawowego w bazie danych dla niektórych tabel

22

Do niektórych moich tabel chcę dodać „second_primary_key”, który będzie identyfikatorem UUID lub jakimś losowym długim kluczem. Potrzebuję tego, ponieważ dla niektórych tabel nie chcę ujawniać liczb całkowitych w mojej aplikacji internetowej. Oznacza to, że na stronie „/ faktury” mam listę faktur i link do „/ faktur /: id” gdzie: id jest liczbą całkowitą. Nie chcę, aby użytkownik wiedział, ile faktur jest w moim systemie, dlatego zamiast „/ invoices / 123” chcę użyć jego „second_primary_key”, aby adres URL miał postać „/ invoices / N_8Zk241vNa”

To samo dotyczy innych tabel, w których chcę ukryć prawdziwy identyfikator.

Zastanawiam się, czy to powszechna praktyka? Jaki jest najlepszy sposób na wdrożenie tego?

A jak się nazywa ta technika, żeby ją wyszukać?

Dari
źródło
20
Dlaczego nie pozbyć się całkowitej liczby całkowitej?
larsbe
4
Możesz zdefiniować dowolną liczbę unikalnych kluczy / indeksów na stole.
abuzittin gillifirca
2
Być może powinieneś nazwać to drugim kluczem kandydata. „Podstawowy” sugeruje tylko jeden.
Walter Mitty,
4
„Drugi pierwotny” to oksymoron. Masz klucz podstawowy i możesz mieć klucze dodatkowe.
Stop Harming Monica,
7
@RobbieDee istnieją ważne powody, dla których baza danych nie jest w pełni znormalizowana. A posiadanie klucza kandydującego lub wtórnego nie do końca powiela dane.
Machado

Odpowiedzi:

0

Możesz dodać kolumnę UUID, ale tak naprawdę nie musisz (i nie powinieneś). To dotyczy warstwy prezentacji. Nie marzyłbyś o powiedzeniu, przechowując wartość waluty jako 1,999 USD, a także 1999.

Chcesz tylko w jakiś sposób ukryć wartość aplikacji w locie. Możesz to zrobić w samej aplikacji lub jako widok bazy danych.

Ponieważ mówimy tylko o jednej wartości, może spójrz na szyfrowanie dwukierunkowe, takie jak AES lub podobne - im bardziej lekkie, tym lepsze.

Hashowanie może być inną możliwością - zależy to od tego, czy chcesz odzyskać numer faktury, ponieważ mieszanie jest jednym ze sposobów.

Robbie Dee
źródło
48

Posiadanie „alternatywnego klucza podstawowego” to dobrze znana koncepcja w modelowaniu relacyjnych baz danych, nazywana jest „kluczem alternatywnym”, a czasem także „kluczem wtórnym”. Zestaw „potencjalnych kluczy podstawowych” nazywa się „kluczami kandydującymi”. Zobacz https://beginnersbook.com/2015/04/alternate-key-in-dbms/

Sposób implementacji zależy wyłącznie od Ciebie, zwłaszcza jeśli chcesz ukryć całkowitą liczbę rekordów. Nie ma „najlepszego sposobu”, powinieneś sprawdzić swoje wymagania, takie jak dozwolony lub użyteczny zestaw znaków, maksymalna długość, jeśli chcesz, aby w identyfikatorach rozróżniana była wielkość liter, czy nie, jeśli chcesz, aby były czytelne na drukowanej fakturze, jeśli ktoś musi być w stanie odpowiedzieć na nie bezbłędnie przez telefon i tak dalej.

Doktor Brown
źródło
11
Widziałem także terminy Klucz naturalny kontra Klucz Zastępczy używane do opisania tego scenariusza.
DanK
2
@Dari: zapytałeś „jak nazywa się ta technika” - pogrubioną czcionką. A jeśli deszyfrowanie AES - może w locie - produkuje klucze, których szukasz, użyj go, co nie jest sprzeczne z moją odpowiedzią.
Doc Brown
1
@Dari Ponieważ dodaje to całkowicie niepotrzebnego obciążenia do Twojej aplikacji
Lamak
1
@RobbieDee Już wiemy, że nie lubisz alternatywnych kluczy, ale to nie znaczy, że są bezużyteczne. Lubię podejście GUID, ponieważ upraszcza wiele problemów.
T. Sar - Przywróć Monikę
1
@RobbieDee Nie używamy SQL Server. Używamy MySql. I dzieje się tak, ponieważ ktoś stworzy coś na Prod, powiedzmy z ID 1234. Na Dev, oczywiście tworzymy o wiele więcej bytów niż robimy na prod. 1234 został zabrany dawno temu przez jakiś wyrzutek do testowania. Kiedy musimy przetestować jednostkę z prod, musimy migrować ją z powrotem do Dev - a jej klucz podstawowy jest już w użyciu. Migracja jest znacznie łatwiejsza, jeśli odwołania do tego obiektu są oparte na GUID. Ale hibernacja działa znacznie lepiej, gdy kluczem podstawowym jest int lub long, więc to utrzymujemy. Moi twórcy nie są leniwi ani nieświadomi - są zaprawieni.
corsiKa
9

Większość faktur ma numer faktury, który według większości zasad rachunkowości musi być sekwencyjny lub księgowy może nie podpisać się z wynikami roku lub IRS (lub podobny w twoim kraju) może chcieć przeprowadzić pełny audyt na twoich kartach.

Użytkownik może wywnioskować z numeru faktury, ilu klientów obsłużyłeś lub ile czasu upłynęło, zanim zmieniłeś strategię numeracji na fakturach.

Liczba faktur przechowywanych w bazie danych nie jest miarą łącznej sumy faktur. Istnieją inne sposoby, aby się tego dowiedzieć, w tym zażądanie raportów rocznych z Izby Handlowej.

Chciałbym jednak zablokować fakturę za ekranem logowania użytkownika, aby nie każdy mógł o to poprosić. Następnie przy logowaniu użytkownika mogą użyć metodologii ajax, aby zażądać zaległych faktur itp. Zabezpiecza to Twoje dane, ukrywa adres URL za pomocą ajax (zwykle nikt nie przejmuje się szczegółami, jak budowane jest zapytanie ajax) , a Ty kontrolujesz sposób wyświetlania i oferowania danych.

Tschallacka
źródło
7
Powszechną strategią stosowaną w bankowości (z numerami czeków) jest nie rozpoczynanie inkrementalnej liczby od 1, ale raczej większa liczba z tego właśnie powodu.
DanK
Myślę, że właśnie dlatego identyfikator ma być dodatkowym kluczem podstawowym, a nie zamiennikiem starego klucza podstawowego.
Alexander
1
Nie nazwałbym tego kluczem podstawowym. Wybrałbym ślimak, UUID jako nazwę, ale w gruncie rzeczy jest to po prostu kolejne indeksowane pole w tabeli. Podaj identyfikator, numer faktury, cokolwiek. To pole, ale nie klucz podstawowy. Klucz podstawowy musi być unikalny i może być używany wewnętrznie do mapowania relacyjnego. Jeśli pole zindeksowane, można je szybko wyszukać według zapytania where. userXveryY.where („numer_faktury”, „foobarbaz10”). get ();
Tschallacka
1
Odpowiadasz na pytanie techniczne, argumentując, że nie jest to konieczne ze względu na specyfikę USA (wymagane kolejne numery faktur, raporty w Izbie Handlowej). IMO nie odpowiada dobrze na pytanie.
RemcoGerlich
7

Możesz użyć do tego hashidów , które mają dokładnie rozwiązać ten scenariusz.

Będzie kodować identyfikator bazy danych w krótkim skrócie (podobnym do adresu URL filmu w YouTube) i nie będzie wymagał dodawania żadnych dodatkowych kluczy do tabeli.

Mitchdav
źródło
2
Nazwa jest nieco myląca, ponieważ nie jest to skrót, ale funkcja odwracalna. Ale wydaje się, że jest to idealne rozwiązanie problemu.
Crazy Yoghurt
2
@CrazyYoghurt Prawda ... zajęli się przyczyną nazwania go tak, jak tutaj: hashids.org/#why-hashids
Eric King
3

Możesz utworzyć kolejny unikalny klucz, ale nie powinieneś. Nie z podanego powodu. Istnieją prostsze sposoby ukrywania rozmiarów tabel.

Przechowywanie N_8Zk241vNakosztuje 12 bajtów na wiersz w tabeli, a nawet więcej w indeksie. To dość marnotrawstwo na to, czego potrzebujesz.

Zaszyfrowanie liczby całkowitej nie idkosztuje miejsca i jest prawie zerowe w czasie wykonywania. Sposób wykonania zależy od języka programowania i / lub bazy danych.

Zauważ, że z AES dostajesz 128-bitową liczbę całkowitą, co oznacza 22 znaki w base64, prawdopodobnie więcej niż chcesz. Szyfr o rozmiarze bloku 64, takim jak DES lub 3DES, daje 11 znaków, tak jak chcesz.

Użyj różnych kluczy dla różnych tabel.

Jeśli wszystko, czego potrzebujesz, to ukrywanie rozmiarów tabel, możesz zastosować wspólną sekwencję dla wszystkich tabel. Pamiętaj, że może być wąskim gardłem, jeśli w wielu twoich tabelach występują częste wstawienia. Z czymś takim jak Hibernacja i algorytm Hi-Lo problem ten znika.

maaartinus
źródło
Dokładnie - przechowywanie tej wartości tylko w celu ukrycia innej jest po prostu błędne.
Robbie Dee,
Może to działać w tym scenariuszu, ponieważ identyfikator faktury nie jest tak naprawdę poufny, ale ogólną zasadą jest, że używanie poufnych identyfikatorów jako struktury relacyjnej w bazie danych spowoduje królewski ból głowy, jeśli będziesz musiał maskować dane w przyszłości. Lepiej traktować je jako atrybut.
DanK
jak mogę tutaj zastosować AES?
Dari,
@Dari Jak możesz zastosować AES do czegokolwiek ? Bez znajomości twojego języka nikt nie może powiedzieć. Zwykle AES współpracuje z a byte[], możesz napisać swój idw czterech lub ośmiu bajtach, dodać unikalny numer tabeli i zaszyfrować (dane wejściowe muszą mieć dokładnie 16 bajtów). Jeśli istnieją tryby do wyboru, EBC ma rację.
maaartinus,
@ DanK Co? Czy twierdzisz, że AES jest niepewny? Bez znajomości klucza atakujący nie może zrobić nic lepszego niż przechowywany atrybut. Nic. +++ Chyba nie rozumiem twojego komentarza.
maaartinus
0

Utworzenie dwóch różnych kluczy podstawowych przez IMHO nie jest możliwe. Oczywiście możesz umieścić ten identyfikator użytkownika w bazie danych, aby mieć go jako „alias” dla bieżącego klucza podstawowego. Możesz umieścić indeks nad tą kolumną z unikalnym ograniczeniem, ale klucz podstawowy jest (z istoty) jednym w obrębie jednej tabeli. Może istnieć złożony klucz podstawowy, ale nie tego szukasz.

Sugeruję więc umieszczenie go tam, ale mając go tylko z indeksem. Możesz utworzyć komponent obsługi dla kwerendy danych według PK, a także innej unikalnej kolumny. Podczas obsługi żądania „/ faktury / ...” po prostu sprawdź parametr - jeśli jest liczbą całkowitą, wyszukaj identyfikator, w przeciwnym razie wyszukaj identyfikator użytkownika. Lub możesz mieć wyszukiwanie UUID jako rezerwowe, gdy wyszukiwanie ID niczego nie znalazło.

A jeśli chodzi o generowanie „losowych” uuidów: dlaczego nie coś w rodzaju „weź ID, dodaj STAŁY, przekonwertuj na szesnastkowy”. Nieprawidłowość ID zapewni unikalność Uuida, liczba szesnastkowa jest trudniejsza do odczytania dla normalnych śmiertelników + dodanie stałej pozwoli uniknąć posiadania UUID takiego jak 00000001.

Jarda
źródło
1
„Dlaczego nie coś takiego:„ weź ID, dodaj STAŁY, przekonwertuj na szesnastkowy ”- bo to dość łatwe do wykrycia - podaj mi adres URL, a ja przejrzę wszystkie inne faktury w systemie. IMO nie ma problemu że to rzeczywiście rozwiązuje, tylko te potencjalnie tworzy.
CompuChip
Podczas obsługi żądania„ / faktur / ... ”po prostu sprawdź parametr - jeśli jest liczbą całkowitą, wyszukaj identyfikator , w przeciwnym razie wyszukaj identyfikator użytkownika ” Cały sens (jak rozumiem pytanie) polega na tym, aby ktoś nie szukał identyfikatora ( /invoices/123, /invoices/124, ...), aby wyszukiwać według UUID tylko z adresu URL.
TripeHound
Ponadto nie wszystkie liczby szesnastkowe zawierają litery. Niemożliwe jest zawsze rozróżnienie między liczbami całkowitymi leżącymi u ich podstaw a wygenerowanymi liczbami szesnastkowymi.
TRiG
@CompuChip, jak się spodziewam, interesują Cię komputery :-), więc rozpoznasz numer szesnastkowy na pierwszy rzut oka. Ale Q zostało napisane w taki sposób, aby nie wyświetlać bezpośrednio numeru faktury, aby inni mogli wiedzieć, ile jest faktur. Kiedy pokażę numer szesnastkowy mojej żonie, matce, sąsiadowi ... nie będą wiedzieć, co to za „dziwny tekst”. Jeśli pojawi się powiadomienie o problemie bezpieczeństwa zgodnie z numerami faktur w Q, sugerowałbym w tym celu jakąś złożoną metodę mieszania.
Jarda
@TripeHound nadal może wyszukiwać według identyfikatora wewnętrznie lub w punkcie wejścia z ograniczonym dostępem ...
Jarda
0

Jeśli oba klucze wskazują na ten sam fakt i nigdy by się nie zderzyły. Dlaczego nie wyprowadzić drugiego klucza z oryginalnego za pomocą funkcji skalarnej, która utworzyłaby niestandardowy kod skrótu oryginalnego klucza.

Alternatywnie możesz utworzyć tabelę mapowania aneksów, w której byłyby przechowywane obie wersje klucza. ta tabela będzie działać jako słownik do wyszukiwania klucza dodatkowego.

Według mojego zrozumienia, klucze są ukrytymi indeksami, a im więcej dodajesz indeksów, tym wolniejsze będą wstawki.

A.Rashad
źródło
+1 Tak, dodanie potencjalnie dużej kolumny z indeksem z pewnością nie jest operacją bez wartości, którą sugerują inni. Oprócz magazynowania, wraz z dodawaniem indeksów szybkość wstawiania zaczyna się obniżać.
Robbie Dee
0

Innym podejściem do konkretnego przypadku użycia jest to, że zamiast modyfikować bazę danych i aplikację, możesz po prostu utworzyć niestandardową trasę do faktur, tak więc / invoices /: f (id) gdzie f (id) jest jakąś funkcją id.

Niestandardowa trasa jest odpowiedzialna za odwzorowanie żądania na właściwą akcję po stronie serwera.


źródło
0

Jest to całkowicie akceptowana praktyka, zwana także „kluczem alternatywnym” (AK). Zasadniczo AK jest kolejnym unikalnym indeksem lub unikalnym ograniczeniem.

Możesz nawet tworzyć ograniczenia klucza obcego na podstawie swojej AK.

Możliwy przypadek użycia jest taki, jak wyjaśniono: masz klastrowaną PK na ciągle rosnącym numerze identyfikacyjnym, ale nie chcesz, aby ten numer był wyświetlany lub używany jako kryterium wyszukiwania, ponieważ można go po prostu zgadnąć. Zatem dodatkowo masz losowy unikalny identyfikator lub numer referencyjny jako AK, i to jest identyfikator, który przedstawiasz użytkownikowi

Alex Schievink
źródło
0

Istnieje kilka rodzajów kluczy / indeksów. Klucz podstawowy jest specjalnym unikalnym indeksem i, jak mówią odpowiedzi, możesz z pewnością stworzyć kolejny unikalny klucz. Zgadzam się, że najlepiej nie ujawniać wewnętrznych elementów bazy danych, chyba że istnieje bardzo uzasadniony powód.

Ponieważ pytanie dotyczy kontekstu faktur i liczb, warto zbadać, jak branża księgowa oczekuje, że wyglądają numery faktur: http://smallbusiness.chron.com/assign-invoice-numbers-52422.html

Może wydawać się niechlujny mieć wewnętrzny identyfikator, który jest kluczem podstawowym i innym unikalnym polem z widocznym numerem faktury aplikacji / klienta. Ale to nie jest tak nieczyste, kiedy, powiedzmy rok później, klient chce przyjąć nowy system numeracji faktur. W takim przypadku nie zakłóciłbyś wewnętrznego identyfikatora i jego relacji w innych tabelach, aby przenumerować całą kulkę wosku. Zachowałbyś swój wewnętrzny identyfikator w stanie, w jakim się znajduje, i ponownie numerujesz numer faktury innej niż wewnętrzna.

Idealnie starasz się nie wiązać ze sobą tabel na kluczach / kluczach obcych, które mogą się zmienić, i utrzymywać wewnętrzne tabele i relacje przezroczyste dla warstwy aplikacji.

Thomas Carlisle
źródło
0

Idź po to.

Nie różni się to od pola „ślimaka”, które często mają artykuły na blogu i tym podobne - unikalny sposób odwoływania się do rekordu bazy danych oddzielonego od klucza podstawowego, nadającego się do użycia w adresie URL. Nigdy nie słyszałem, żeby ktokolwiek się z nimi sprzeczał.

RemcoGerlich
źródło