Có thể giới hạn mức sử dụng đĩa tối đa cho người dùng


7

Có thể đặt giới hạn về dung lượng ổ đĩa vật lý mà người dùng (hoặc nhóm người dùng) có thể sử dụng trong một cơ sở dữ liệu không? Ví dụ, có một số phương pháp liên kết lược đồ với nhóm fileg và sau đó đặt kích thước tối đa cho filegroup? Cơ sở dữ liệu thực tế sẽ có các bảng khác trên đó và do đó muốn có các nhóm fileg khác không giới hạn.


Những người dùng này sẽ tạo các bảng riêng của họ theo ý muốn?
Aaron Bertrand

Có, người dùng sẽ tạo các bảng của riêng họ theo ý muốn.

Câu trả lời:


10

Nếu người dùng của bạn đã tạo quyền trong lược đồ của riêng họ, thì bạn có thể thiết lập trình kích hoạt DDL để nắm bắt việc tạo bảng xảy ra trên một nhóm tệp khác với nhóm bạn đã liên kết với người dùng đó. Bạn không thể ngăn bảng được tạo, nhưng bạn có thể cuộn lại và trả về thông báo lỗi.

Trước tiên, hãy thêm một nhóm và một tệp có kích thước tối đa vào cơ sở dữ liệu hiện có:

USE [master];
GO

ALTER DATABASE floob ADD FILEGROUP SomeUser;
GO

ALTER DATABASE floob ADD FILE 
(
  NAME = SomeUser, 
  FILENAME = 'C:\...wherever...\floob_SomeUser.mdf',
  MAXSIZE = 20MB -- your quota, this part is important!
) TO FILEGROUP SomeUser; -- this part is also important!
GO

Bây giờ hãy tạo một lược đồ và đăng nhập có thể kiểm soát lược đồ đó:

CREATE SCHEMA SomeUser;
GO

CREATE LOGIN SomeUser WITH PASSWORD = 'foo', CHECK_POLICY = OFF;
GO

USE floob;
GO

CREATE USER SomeUser FROM LOGIN [SomeUser] WITH DEFAULT_SCHEMA = SomeUser;
GO

GRANT CONTROL ON SCHEMA::SomeUser TO dbo;
GRANT CREATE TABLE TO SomeUser;
GO

Trước hết, với các cài đặt này, người dùng này không thể tạo các bảng trong dbo hoặc bất kỳ lược đồ nào khác ngoài bảng của họ, điều đó có nghĩa là theo mặc định, họ sẽ chỉ có thể tạo các bảng trên tệp giới hạn của họ [nhóm]. Nếu bạn kết nối với cơ sở dữ liệu floob với tư cách là người dùng này và cố gắng tạo bảng trong dbo:

CREATE TABLE dbo.foo(id INT);

Bạn nhận được lỗi này:

Msg 2760, Cấp 16, Trạng thái 1, Dòng 1
Tên lược đồ được chỉ định "dbo" không tồn tại hoặc bạn không có quyền sử dụng nó.

Và do default_schema của người dùng này, việc không chỉ định lược đồ someUser vẫn sẽ kết thúc với một bảng được tạo trong someUser (mặc dù bạn thực sự nên thúc đẩy các thực tiễn tốt nhất ở đây, đặc biệt là trong trường hợp này và luôn chỉ định tên lược đồ khi tạo hoặc tham chiếu các đối tượng ).

Bây giờ chúng ta có thể tạo một trình kích hoạt như thế này, nó sẽ khôi phục toàn bộ lô trong trường hợp nhóm filegroup không được chỉ định:

CREATE TRIGGER EnsureFilegroup
ON DATABASE
FOR CREATE_TABLE
AS
BEGIN
  DECLARE @e XML = EVENTDATA();

  IF @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)') = N'SomeUser'
     AND NOT EXISTS (SELECT 1 FROM sys.indexes AS i INNER JOIN sys.data_spaces AS d
       ON i.data_space_id = d.data_space_id
       WHERE d.name = N'SomeUser'
       AND i.[object_id] = OBJECT_ID(
        QUOTENAME(@e.value('(/EVENT_INSTANCE/SchemaName)[1]',  'NVARCHAR(128)'))
        + '.' + QUOTENAME(@e.value('(/EVENT_INSTANCE/ObjectName)[1]',  'NVARCHAR(128)')))
       AND i.index_id IN (0,1))

  BEGIN
    RAISERROR('You must place your objects on the SomeUser filegroup.', 11, 1);
    ROLLBACK TRANSACTION;
  END
END
GO

Nó đặc biệt tiện dụng để giữ cho tên người dùng, lược đồ và tên nhóm giống nhau, điều này sẽ giúp việc này dễ dàng hơn khi lập trình. Trước tiên, bạn có thể thực hiện kiểm tra xem lược đồ đang được sử dụng không phải là một trong các lược đồ "có giới hạn" của bạn, sau đó tiến hành kiểm tra so sánh tên lược đồ với tên tệp filegroup. Nếu nó không khớp, người dùng này có quyền đối với lược đồ sai và đang cố tạo các đối tượng ở sai vị trí và một lỗi sẽ được đưa ra:

ALTER TRIGGER EnsureFilegroup
ON DATABASE
FOR CREATE_TABLE
AS
BEGIN
  DECLARE @e XML = EVENTDATA();

  IF @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)') <> N'dbo'
    -- or NOT IN (N'dbo', N'other unlimited schemas')
  BEGIN

    IF NOT EXISTS (SELECT 1 FROM sys.indexes AS i INNER JOIN sys.data_spaces AS d
       ON i.data_space_id = d.data_space_id
       WHERE d.name = @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)')
       AND i.[object_id] = OBJECT_ID(
        QUOTENAME(@e.value('(/EVENT_INSTANCE/SchemaName)[1]',  'NVARCHAR(128)'))
        + '.' + QUOTENAME(@e.value('(/EVENT_INSTANCE/ObjectName)[1]',  'NVARCHAR(128)')))
       AND i.index_id IN (0,1))
    BEGIN
      RAISERROR('You must place your objects on your own filegroup.', 11, 1);
      ROLLBACK TRANSACTION;
    END
  END
END
GO

2
Tốt thứ Aaron. Rất đẹp.
RBarryYoung

1
Chỉ cần yêu thích trình kích hoạt của Surefilegroup
Edward tổng hợp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.