web-dev-qa-db-fra.com

Comment Uniqueidentifier dans SQL Server est toujours une valeur unique à l'échelle mondiale?

Selon la documentation Microsoft sur UniqueIdentifier, cette valeur est toujours une beacuse globale unique, elle est basée sur l'horloge du réseau et le temps d'horloge du processeur et, d'autre part, la même documentation dit

les colonnes uniqueidentifier peuvent contenir plusieurs occurrences d'une valeur individuelle uniqueidentifier, sauf si les contraintes UNIQUE ou PRIMARY KEY sont également spécifiées pour la colonne.

Je ne suis pas en mesure de conclure comment UniqueIdentifier (GUID) peut être unique à l'échelle mondiale, car l'adresse réseau (adresse Mac) peut être la même sur deux réseaux différents, comment les GUID peuvent être uniques à l'échelle mondiale avec quelles combinaisons et pourquoi Microsoft dit-il doit être une contrainte principale ou unique afin de garantir que nous avons toujours une valeur UniqueIdeitifer unique.

https://technet.Microsoft.com/en-us/library/ms190215 (v = sql.105) .aspx

7
Viswanathan Iyer

Problème n ° 1

Selon la documentation Microsoft sur UniqueIdentifier, cette valeur est toujours unique au niveau mondial car elle est basée sur l'horloge du réseau et le temps d'horloge du CPU ... (pas d'italique dans l'original)

Le principal problème ici est que vous confondez deux choses différentes comme étant deux termes qui font référence à une seule chose: UNIQUEIDENTIFIER et GUID.

  • UNIQUEIDENTIFIER est un type de données. Les types de données définissent la nature des données qu'ils peuvent contenir (c'est-à-dire les colonnes et les variables de ce type) (par exemple, les valeurs min/max, etc.) et certains comportements des données (par exemple, comment gérer les comparaisons). Ce type de données particulier contient simplement GUID/UUID. Mais ce ne sont pas des données, donc le concept d'unicité ne s'applique pas à lui. Et le Le mot "Unique" dans le nom "UniqueIdentifier" n'est pas une promesse, ni même une déclaration, concernant l'unicité réelle.

  • Les GUID/UUID sont des valeurs réelles qui peuvent être stockées en tant que UNIQUEIDENTIFIER, mais peuvent également être stockées en tant que VARBINARY/BINARY, (N)VARCHAR/(N)CHAR, Et peut-être quelques autres. Bien que le type de données UNIQUEIDENTIFIER soit le meilleur choix (dans SQL Server) pour stocker ces valeurs, le stockage des valeurs dans les autres types ne rend pas les valeurs plus ou moins uniques.

Problème n ° 2

Je ne suis pas en mesure de conclure comment UniqueIdentifier (GUID) peut être unique à l'échelle mondiale, car l'adresse réseau (adresse Mac) peut être la même sur deux réseaux différents

Le deuxième problème ici est que vous acceptez, comme fait, une erreur technique dans la documentation à laquelle vous avez lié. Je suppose que vous faites référence à cette déclaration:

A GUID est un nombre binaire unique; aucun autre ordinateur au monde ne générera un doublon de cette valeur GUID.

Cette instruction fait référence à des fonctions telles que NEWID() dans T-SQL et Guid.NewGuid() dans .NET qui créent de nouvelles valeurs GUID/UUID et les intention d'entre eux de toujours générer des valeurs uniques. Cependant, ce n'est pas la réalité: les GUID nouvellement générés ne sont pas garantis d'être uniques. Comme vous déjà souligné, les adresses MAC ne sont pas nécessairement uniques (elles peuvent même être usurpées; plus d'informations dans la section "Informations connexes" ci-dessous). De plus, à partir d'autres documentations Microsoft:

  • Page MSDN pour .NET Structure Guid états (soulignement ajouté):

    A GUID est un entier de 128 bits (16 octets) qui peut être utilisé sur tous les ordinateurs et réseaux partout où un identifiant unique est requis. Un tel identifiant a un très faible probabilité d'être dupliquée.

  • La méthode .NET Guid.NewGuid () (qui est utilisée pour générer de nouvelles GUID/valeurs UUID)) appelle Win32Native.CoCreateGuid . documentation pour cette fonction indique (emphase ajoutée):

    Avec un degré de certitude très élevé , cette fonction renvoie une valeur unique - aucune autre invocation, sur le même système ou sur tout autre système (en réseau ou non), devrait retourner la même valeur.

Veuillez noter que la documentation non SQL Server ne mentionne même pas l'adresse MAC. Et la documentation de CoCreateGuid pointe vers la fonction réelle qui fait la génération: idCreate . La documentation de cette fonction indique:

Pour des raisons de sécurité, il est souvent souhaitable d'empêcher les adresses Ethernet des réseaux d'être disponibles en dehors d'une entreprise ou d'une organisation. La fonction UuidCreate génère un UUID qui ne peut pas être retracé à l'adresse Ethernet de l'ordinateur sur lequel il a été généré. Il ne peut pas non plus être associé à d'autres [~ # ~] uuid [~ # ~] créés sur le même ordinateur. Si vous n'avez pas besoin de ce niveau de sécurité, votre application peut utiliser la fonction idCreateSequential , qui se comporte exactement comme la fonction UuidCreate fait sur toutes les autres versions du système d'exploitation.

L'implication ici est que l'adresse MAC n'est spécifiquement pas utilisée (sauf en utilisant NEWSEQUENTIALID()). Et en fait, la génération de quelques GUID dans SQL Server via NEWID() indique qu'ils sont RFC 4122, version 4 UUID, qui sont extrêmement probables être unique. Il y a un graphique ici, probabilité UUID aléatoire de doublons , qui montre à quel point il est peu probable d'avoir des doublons. Cependant, même une très, très faible probabilité de doublons n'est pas pas une garantie d'unicité.

Et donc...

Il n'y a pas garantie que les valeurs GUID/UUID nouvellement générées sont uniques. Et, même s'il y avait une garantie, le UNIQUEIDENTIFIER le type de données n'aurait toujours rien à voir avec l'unicité réelle (comme le montre la réponse de Brent). Unicité, pour une ou plusieurs colonnes (c'est-à-dire les données, pas les types de données) ne peut être appliqué que par des index/contraintes uniques.


Informations connexes:

11
Solomon Rutzky

Parce qu'une colonne UNIQUEIDENTIFIER peut stocker tout UNIQUEIDENTIFIER que vous y mettez. Prenez ce code:

CREATE TABLE dbo.Test (MyID UNIQUEIDENTIFIER);
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
SELECT * FROM dbo.Test;

Rien ne vous empêche de le faire - à moins que vous ne spécifiiez quelque chose sur la table qui applique l'unicité.

7
Brent Ozar