ในตอนล่าง (ผู้เช่า 500 คน / ผู้ใช้ 10,000 คน) นี่คือสิ่งที่ฉันทำ ก่อนอื่นคุณมีฐานข้อมูล "ควบคุม" ที่เป็นส่วนกลางส่วนกลางและมีข้อมูลทั้งหมดเกี่ยวกับผู้เช่าและผู้ใช้ (ฉันไม่คิดว่าคุณต้องการจัดการสิ่งเหล่านี้ในการเข้าสู่ระบบรับรองความถูกต้องของ SQL) ลองนึกภาพฐานข้อมูลที่เรียกว่า "การควบคุม" ด้วยตารางต่อไปนี้:
CREATE TABLE dbo.Instances
(
InstanceID INT PRIMARY KEY,
Connection VARCHAR(255)
--, ...
);
INSERT dbo.Instances SELECT 1, 'PROD1\Instance1';
INSERT dbo.Instances SELECT 1, 'PROD2\Instance1';
-- ...
CREATE TABLE dbo.Tenants
(
TenantID INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL UNIQUE,
InstanceID INT -- Foreign key tells which instance this tenant's DB is on
--, ...
);
INSERT dbo.Tenants SELECT 1, 'MyTenant', 1;
-- ...
CREATE TABLE dbo.Users
(
UserID INT PRIMARY KEY,
Username VARCHAR(320) NOT NULL UNIQUE,
PasswordHash VARBINARY(64), -- because you never store plain text, right?
TenantID INT -- foreign key
--, ...
);
INSERT dbo.Users SELECT 1, 'foo@bar.com', 0x43..., 1;
ในกรณีของเราเมื่อเราเพิ่มผู้เช่าใหม่เราจะสร้างฐานข้อมูลแบบไดนามิก แต่ไม่ใช่เมื่อผู้ใช้ผู้ดูแลระบบคลิกตกลงใน UI ... เรามีงานพื้นหลังที่ดึงฐานข้อมูลใหม่ออกจากคิวทุก ๆ 5 นาทีตั้งค่าแบบจำลองเป็น single_user แล้วสร้างแต่ละฐานข้อมูลใหม่ตามลำดับ เราทำสิ่งนี้เพื่อ (ก) ป้องกันผู้ใช้ที่เป็นผู้ดูแลจากการรอการสร้างฐานข้อมูลและ (b) เพื่อหลีกเลี่ยงผู้ใช้ที่ดูแลระบบสองคนที่พยายามสร้างฐานข้อมูลในเวลาเดียวกันหรือมิฉะนั้นการปฏิเสธความสามารถในการล็อคแบบจำลอง )
ฐานข้อมูลถูกสร้างขึ้นด้วยรูปแบบชื่อTenant000000xx
ที่เป็นตัวแทนxx
Tenants.TenantID
งานนี้ทำให้การบำรุงรักษาค่อนข้างง่ายแทนที่จะมีทุกชนิดของฐานข้อมูลชื่อBurgerKing
, McDonalds
, KFC
ฯลฯ ไม่ว่าเราอยู่ในอาหารอย่างรวดเร็วเพียงแค่ใช้ที่เป็นตัวอย่าง
เหตุผลที่เราไม่ได้จัดสรรฐานข้อมูลนับพันไว้ล่วงหน้าเนื่องจากความคิดเห็นที่แนะนำคือผู้ใช้ผู้ดูแลระบบของเรามักจะมีความคิดว่าผู้เช่าจะมีขนาดใหญ่ขึ้นไม่ว่าพวกเขาจะมีลำดับความสำคัญสูง ฯลฯ ดังนั้นพวกเขาจึงมีตัวเลือกพื้นฐานใน UI จะกำหนดขนาดเริ่มต้นและการตั้งค่า autogrowth ซึ่งระบบย่อยของดิสก์ข้อมูล / ล็อกไฟล์ของพวกเขาจะไปที่การตั้งค่าการกู้คืนของพวกเขากำหนดการสำรองข้อมูลเพื่อบานพับออกและแม้แต่ฉลาดเกี่ยวกับอินสแตนซ์ที่จะปรับใช้ฐานข้อมูล แม้ว่าผู้ดูแลระบบของเราสามารถแทนที่สิ่งนี้ได้) เมื่อสร้างฐานข้อมูลแล้วตารางผู้เช่าจะได้รับการอัปเดตด้วยอินสแตนซ์ที่เลือกผู้ใช้ที่เป็นผู้ดูแลระบบจะถูกสร้างขึ้นสำหรับผู้เช่าและผู้ดูแลระบบของเราจะส่งข้อมูลประจำตัวเพื่อส่งผ่านไปยังผู้เช่ารายใหม่
หากคุณกำลังใช้การเข้าสู่จุดเดียวมันเป็นไปไม่ได้ที่จะอนุญาตให้ผู้เช่าหลายคนมีผู้ใช้ที่มีชื่อผู้ใช้เดียวกัน เราเลือกที่จะใช้ที่อยู่อีเมลซึ่งหากผู้ใช้ทุกคนทำงานให้กับ บริษัท และใช้ที่อยู่อีเมล บริษัท ของพวกเขาควรจะถูกต้อง แม้ว่าวิธีการแก้ปัญหาของเราจะซับซ้อนกว่าด้วยเหตุผลสองประการ:
- เรามีที่ปรึกษาที่ทำงานให้กับลูกค้าของเรามากกว่าหนึ่งคนและต้องการการเข้าถึงหลายคน
- เรามีผู้เช่าที่ตัวเองประกอบไปด้วยผู้เช่าหลายคน
ดังนั้นเราจึงลงเอยด้วยTenantUsers
ตารางที่อนุญาตให้ผู้ใช้หนึ่งคนเชื่อมโยงกับผู้เช่าหลายคน
เริ่มแรกเมื่อผู้ใช้ลงชื่อเข้าใช้แอปจะรู้สตริงการเชื่อมต่อสำหรับฐานข้อมูลการควบคุมเท่านั้น เมื่อล็อกอินสำเร็จจะสามารถสร้างสตริงการเชื่อมต่อตามข้อมูลที่พบ เช่น
SELECT i.Connection
FROM dbo.Instances AS i
INNER JOIN dbo.Tenants AS t
ON i.InstanceID = t.InstanceID
INNER JOIN dbo.TenantUsers AS u
ON i.TenantID = u.TenantID
WHERE u.UserID = @UserID;
ตอนนี้แอปสามารถเชื่อมต่อกับฐานข้อมูลของผู้ใช้ (ผู้ใช้แต่ละคนมีผู้เช่าเริ่มต้น ) หรือผู้ใช้สามารถเลือกจากผู้เช่าใด ๆ ที่พวกเขาสามารถเข้าถึง จากนั้นแอปจะเรียกค้นสตริงการเชื่อมต่อใหม่และเปลี่ยนเส้นทางไปยังหน้าแรกสำหรับผู้เช่ารายนั้น
หากคุณเข้าสู่พื้นที่ผู้ใช้ 10 มม. ที่คุณเสนอคุณจะต้องได้สิ่งนี้เพื่อความสมดุลที่ดีขึ้น คุณอาจต้องการรวมแอปพลิเคชันเพื่อให้มีจุดเชื่อมต่อที่แตกต่างกันไปยังฐานข้อมูลการควบคุมที่แตกต่าง หากคุณให้โดเมนย่อยแก่ผู้เช่าแต่ละคน (เช่น TenantName.YourApplicationDomain.com) จากนั้นคุณสามารถทำสิ่งนี้เบื้องหลังกับ DNS / การกำหนดเส้นทางโดยไม่รบกวนพวกเขาเมื่อคุณต้องการขยายเพิ่มเติม
มีอะไรอีกมากมายในนี้ - เช่น @Darin ฉันแค่เกาที่นี่เท่านั้น แจ้งให้เราทราบหากคุณต้องการคำปรึกษาฟรี :-)