Как я могу генерировать уникальные имена пользователей в общей базе данных одновременно? - PullRequest
1 голос
/ 26 сентября 2011

Мне нужно автоматически создавать имена учетных записей. Они будут использоваться в пользовательском программном обеспечении, которое будет обращаться к моему сервису, поэтому они не обязательно выглядят симпатично. Я думаю, что любая буквенно-цифровая строка достаточно долго подойдет. Предположим, у меня уже есть алгоритм, который выдает достаточно хорошую буквенно-цифровую строку.

Существует два основных требования: они должны быть уникальными и генерироваться одновременно. В частности, моя служба будет работать на нескольких машинах, и все копии будут иметь доступ к одной и той же общей базе данных. Мне нужно сгенерировать эти имена пользователей таким образом, чтобы никакие два узла никогда не генерировали идентичные имена пользователей.

Как мне это сделать? Я просто оставляю эту идею и использую GUID? Есть ли более симпатичный способ использования GUID для этого сценария?

Ответы [ 2 ]

2 голосов
/ 26 сентября 2011

Один из:

  • Использовать GUID (тип данных uniqueidentifier), но не как кластеризованный индекс
  • Использовать столбец IDENTITY

Если SQL Serverрепликация используется на нескольких узлах (Правка: раньше слишком много думал)

  • Использовать столбцы IDENTITY с диапазонами, заданными для узла (например, от -1 до -1000000, от 1 до 100000 и т. д.)
  • Столбец IDENTITY и столбец NodeID для разделения значений IDENTITY

Все они безопасны для параллелизма

0 голосов
/ 26 сентября 2011
CREATE TABLE dbo.CommonName
(
    CommonNameID INT IDENTITY(0,1) PRIMARY KEY
    ,Name NVARCHAR(50) NOT NULL
    ,LastID INT NOT NULL DEFAULT 0
);
INSERT  dbo.CommonName(Name)
VALUES  
 ('JAMES')  
,('JOHN')   
,('ROBERT') 
,('MICHAEL')    
,('WILLIAM')    
,('DAVID')  
,('RICHARD')    
,('CHARLES')    
,('JOSEPH') 
,('THOMAS');
GO

--Test
CREATE TABLE [User](Id INT IDENTITY(1,1) PRIMARY KEY, UserName NVARCHAR(60));
GO

UPDATE  dbo.CommonName WITH(ROWLOCK)
SET     
        LastID = LastID + 1
OUTPUT  inserted.Name+CAST(inserted.LastID AS NVARCHAR(10)) INTO [User](UserName)
WHERE   CommonNameID = ABS(CHECKSUM(NEWID())) % 10
GO 20 --We need 20 new users

SELECT  *
FROM    [User] u
ORDER BY u.Id;
--End of test
GO

DROP TABLE dbo.CommonName;
DROP TABLE dbo.[User];

Пример вывода:

Batch execution completed 20 times.
Id          UserName
----------- ------------------------------------------------------------
1           RICHARD1
2           MICHAEL1
3           ROBERT1
4           WILLIAM1
5           ROBERT2
6           JAMES1
7           CHARLES1
8           RICHARD2
9           JOSEPH1
10          THOMAS1
11          ROBERT3
12          MICHAEL2
13          WILLIAM2
14          MICHAEL3
15          THOMAS2
16          THOMAS3
17          WILLIAM3
18          RICHARD3
19          JAMES2
20          RICHARD4

(20 row(s) affected)

Если вы хотите проверить этот код на наличие проблем параллелизма, вы можете запустить UPDATE ...; GO 100000 и UPDATE ...; GO 100 в SSMS в двух отдельных окнах / запросах и наВ конце концов, вы можете выполнить этот запрос SELECT UserName, COUNT(*) Num FROM dbo.[User] ORDER BY COUNT(*) DESC, чтобы посмотреть, сможете ли вы найти дубликаты.

...