خانه SQL Server آشنایی با SQL Server 2016 Row Level Security – محدودیت ها و کارایی (بخش سوم) SQL Server امنیت SQL Server نوشته شده توسط: سید محمد حسینی تاریخ انتشار: ۰۹ خرداد ۱۳۹۵ آخرین بروزرسانی: 30 دی 1403 زمان مطالعه: 20 دقیقه ۵ (۱) مفهوم Row Level Security، در دو مقاله قبل با RLS و نحوه استفاده از آن در SQL Server 2016 آشنا شدیم. در ادامه قصد دارم چند نکته را که باید پیش از استفاده از RLS و هر گونه پیاده سازی از آنها آگاهی داشته باشیم، مورد بررسی قرار دهم. با توجه به اینکه RLS در SQL Server 2016 معرفی شده است، دارای محدودیت هایی نیز هست. در ادامه قصد داریم با این محدودیت ها آشنا شده و برخی از کارهایی را که می توان برای کم کردن یا جبران این محدودیت ها انجام داد(در برخی موارد) را ارائه دهیم. البته باید این نکته را هم بگویم که برخی از این محدودیت ها موقتی هستند و با ارائه نسخه نهایی SQL Server 2016 بر طرف خواهند شد(نسخه استفاده شده در زمان نگارش CTP 2.2). محدودیت های RLS در SQL Server 2016 در این بخش از مقاله به محدودیت های RLS در SQL Server 2016 می پردازیم با ما همراه باشید: مفهوم SCHEMABINDING همان طور که در مقالات قبل ذکر شد، تابع گزاره ای(Predicate Function) حتما باید با قید WITH SCHEMABINDING ایجاد گردد. در صورتی که این تابع بدون این تنظیم ایجاد گردد و قصد اتصال آن به سیاست امنیتی(Security Policy) را داشته باشیم، با خطای زیر مواجه خواهیم شد. Msg 4513, Level 16 Cannot schema bind security policy ‘policy’. ‘dbo.function’ is not schema bound این محدودیت نه تنها ما را در دسترسی به Catalog Viewها و DMVهای محلی محدود می کند، بلکه قادر به پیاده سازی منطق های امنیتی مبتنی بر جداول Lookup که در سایر بانک های اطلاعاتی ذخیره شده اند نیز نخواهیم بود – این به این معنی است که اگر ما یک لیست کنترل دسترسی ذخیره شده مرکزی داشته باشیم(در جایی دیگر)، می خواهیم با استفاده از viewها، Synonemها و یا پرسوجوهایی به این بانک اطلاعاتی مراجعه کنیم، یا داده ها و اطلاعات اصلی را به این بانک اطلاعاتی منتقل کنیم و یا مراجعات دیگری داشته باشیم. مفهوم Indexed Views RLS با جداولی که دارای Indexed View هستند سازگاری ندارد. در صورتی که بخواهیم یک Indexed View بر روی جدولی که دارای سیاست امنیتی تعریف شده است ایجاد کنیم، با خطای زیر مواجه می شویم. Msg 33266, Level 16 The index on the view ‘view’ cannot be created because the view is referencing table ‘table’ that is referenced by a security policy. این همان قضیه مرغ و تخم مرغ است، در صورتی که جدولی هم به یک Indexed View ارجاع داده باشد، سیاست امنیتی نمی تواند به آن جدول تخصیص داده شود. Msg 33265, Level 16 The security policy ‘policy’ cannot have a predicate on table ‘table’ because this table is referenced by the indexed view ‘view’. همچنین در صورتی که قصد ایجاد سیاست امنیتی بر روی جدولی را داشته باشیم که توسط Partitioned View به آن ارجاع شده است نیز با خطاهای مشابهی مواجه خواهیم شد. مفهوم In-Memory OLTP در این نسخه از SQL Server 2016(CTP 2.2) جداول نسخه In-Memory OLTP پشتیبانی نمی شوند. البته احتمال اینکه این جداول در نسخه RTM پشتیبانی شوند بسیار زیاد است. زیرا مایکروسافت قصد دارد تا ویژگی های جدید، تمامی قابلیت های موتور اصلی بانک اطلاعاتی (نظیر Columnstore) را پشتبیانی کنند مفهوم Change Data Capture CDC نیز در SQL Server 2016 پشتیبانی نشده است. نسخه جاری امکان فعال سازی CDC را بر روی جدولی که سیاست امنیتی برای آن تخصیص داده شده است را می دهد، و همچنین می توان سیاست امنیتی را بر روی جدولی که CDC برای آن فعال شده است، تخصیص داد، اما به احتمال زیاد در نسخه RTM این قابلیت مسدود خواهد شد(در صورت عدم حذف نیز پشتیبانی نخواهد شد). مفهوم Full-Text Indexes ایندکس های Full-Text مورد پشتیبانی قرار گرفته اند، ولی باید به یاد داشته باشید که ایندکس ها بر اساس داده های فیلتر نشده هستند. البته به رغم سیاست امنیتی تعیین شده برای جدول ممکن است در مواردی با نشتی اطلاعات مواجه شویم. تاثیر RLS بر کارایی SQL Server مفهوم Row Level Security، در پرس و جوهای SELECT، برای فیلتر کردن سطرها قطعا تاثیر قابل توجهی در پلان اجرایی مشاهده خواهد شد. در بیشتر موارد عملگر Left Semi Join در کنار جدول/جداولی که از تابع گزاره ای استفاده می کنند قابل مشاهده است. در زیر پلان اجرایی دو پرس و جوی * SELECT آورده شده است. پرس و جوی اول بدون سیاست امنیتی اجرا شده است و اجرای پرس وجوی دوم به همراه فیلتر سازی در سطح سطر می باشد. چیزی که از تصویر فوق می توان مشاهده کرد، این است که منطق و عملگرهای inline TVF در پلان اجرایی پرسوجوی اول وجود ندارند، همچنین بهینه کردن تابع گزاره ای جهت کمتر شدن تاثیر آن در اجرای پرسوجو می تواند به میزان بسیار زیادی اهمیت داشته باشد. این که RLS چه میزان می تواند در کارایی و حجم کاری ما تاثیر گذار باشد به عوامل گوناگون و متفاوتی وابسته است – نظیر الگوی پرسوجو، منطق استفاده شده در تابع گزاره و… نکته قابل توجه دیگر این است که، کاربرانی که عضو sysadmin، db_owner، db_ddladmin و مالک(owner) جدول نیستند، دسترسی مستقیم به DBCC SHOW_STATISTICS ندارند – زیرا این مسئله می تواند موجب نشت اطلاعات شود. بدیهی hست که ما باید برنامه کاربری را به طور کامل از نظر رفتار و عوامل کاهنده کارایی مورد تست قرار دهیم. در ادامه با یک مثال دیگر، میزان تاثیرات RLS بر کارایی را بیشتر بررسی خواهیم کرد. عیب یابی RLS در SQL Server به طور پیش فرض، dbo و sysadmin قادر به دسترسی به تمامی سطرهای جدول نیستند. در صورتی که ما نیاز به عیب یابی پرسوجوها، تکرار برخی کارها، یا حتی بازبینی معمولی اطلاعات را داشته باشیم، باید اطمینان یابیم که تابع گزاره ای اجازه این کار را به ما می دهد، یا اینکه با کاربری که دارای دسترسی کامل است با بانک اطلاعاتی کار کنیم(در کدهایی که در ادامه آورده شده است، چنین کاربری ایجاد شده است). همچنین، امکان به وجود آمدن یک پلان اجرایی پیچیده برای یک پرس وجوی نسبتا ساده دور از انتظار نبوده و می تواند موجب سر در گمی گردد. از طرفی درک این مسئله می تواند برای کاربران مشکل ساز شود که چرا اشیاء مربوط به تابع گزاره ای در پلان اجرایی ظاهر شده اند، در حالی که هیچ تابعی یا هیچ یک از آن اشیاء در متن پرس وجو استفاده نشده اند. نشت اطلاعات در RLS مفهوم Row Level Security، چندین روش برای کار کردن کاربران در محدوده RLS وجود دارد. همانطور که در قبل گفته شد، ایندکس های Full Text می توانند موجب بروز مشکل شوند، ولی چندین مسئله وجود دارد که باید آنها را به خاطر داشت. مفهوم Policy Managers and Collusion همانطور که قبلا گفته شد، حتی کاربران dbo و sysadmin نیز قادر به دستیابی به تمامی اطلاعات جدول نیستند مگر اینکه صراحتا از تابع گزاره ای مجوز داشته باشند. البته، اگر کاربری مسئول مدیریت سیاست های امنیتی باشد و امکان اعمال تغییرات در توابع مورد استفاده در سیاست ها را دارا باشد، می تواند به سادگی با اعمال تغییر در منطق به این هدف برای خود دست یابد(البته این مورد را می توان به سادگی با استفاده از تریگرهای DDL مانیتور کرد)، و یا می تواند جهت قابل مشاهده شدن سایر سطرها برای برخی کاربران با آنها تبانی کند، همچنین می تواند به سادگی سیاست امنیتی را برای مدتی موقتا غیر فعال کند (البته این کار می تواند مورد بازبینی و حسابرسی قرار گیرد). در اینجا لیست کاملی از کارهای مخربی که مدیر سیاست امنیتی می تواند انجام دهد آورده شده است. مفهوم CONTEXT_INFO</span> <div>مفهوم Row Level Security، اگر قصد داشته باشیم که مثلا در یک برنامه وب فیلترکردن در سطح سطر را پیاده سازی کنیم. به طوری که تمامی کاربران با یک نام کاربری مشترک لاگین کنند(در SQL Server) این کار را می توان از طریق ارسال اطلاعات خاص هر کاربر به () CONTEXT_INFO انجام داد. مشکلی که در اینجا رخ می دهد این است که، در صورتی که هر کاربری توانایی اجرای پرسوجوی ad hoc را داشته باشد، می توانند از () CONTEXT_INFO کلاهبرداری کنند. در مثال زیر کاربر Poen می تواند اطلاعات هر کاربری را مشاهده کند.. توجه: کدهای مورد نیاز برای ایجاد جداول، کاربران، تابع گزاره ای و سیاست امنیتی جهت اجرای این مثال و مثال های بعد، در انتهای این بخش و با عنوان کد های تکمیلی قرار داده شده است. EXECUTE AS USER = N'Peon'; GO DECLARE @ci VARBINARY(128) = CONVERT(VARBINARY(128),N'Rep1'); SET CONTEXT_INFO @ci; SELECT USER_NAME(), * FROM dbo.Accounts; GO REVERT; GO راه حل مناسب در اینجا می تواند افزودن Dynamic data masking، Column-level encryption یا انواع hashing/obfuscation/salting برای نام کاربری Rep1 باشد، در این صورت کاربر مخرب نمی تواند از محتویات () CONTEXT_INFO اطلاع یابد. ولی در حالت کلی، می بایست دسترسی به این داده ها را در تمامی SPها و در درون کد برنامه کنترل کنیم، حتی اگر دسترسی مستقیم به پرس وجوهای ad hoc وجود نداشته باشد. مفهوم Clever ad hoc queries در برخی مواقع که کاربر به سطرها دسترسی ندارد، می تواند پرس وجو را به گونه ای بنویسد که اطلاعات مختصری را در مورد سطرها به دست آورد. در مثال زیر کاربر Poen می تواند به دست آورد که کدام یک از کاربران ?Rep دارای رکوردی با شرط AnnualFees>75000$ است. EXECUTE AS USER = N'Peon'; GO DECLARE @i INT = 1; BEGIN TRY SELECT * FROM dbo.Accounts WHERE CASE WHEN RepID = @i THEN CASE WHEN AnnualFees > 75000 THEN CONVERT(INT, 'x') -- designed to raise an exception END END = 1; END TRY BEGIN CATCH PRINT N'Rep ' + RTRIM(@i) + N' has an account with fees > $75,000.'; END CATCH GO REVERT; GO در صورتی که یک حلقه ایجاد کنیم و در آن i@ را افزایش دهیم، با اجرای این کد، برای هر یک از کاربران ?Rep که دارای رکوردی با شرط AnnualFees>75000$ است اطلاعات مختصری چاپ می شود. این کد اجرا می شود زیرا برخی از عبارت ها پیش از اینکه فیلتر کردن در سطح سطر اعمال شود، ارزیابی می شوند. بنابراین با تکرار و کمی تلاش می توان مواردی را به دست آورد که اطلاعات کامل تری در مورد سایر سطرهای جدول در اختیار ما قرار دهد(البته کاربران مخرب قطعا این تکرار و تلاش را دارند) – این مثال بسیار خوب است، فرض کنید در جدول HR که شما می توانید میزان حقوق خود را ببینید؛ با استفاده از پرسوجوهای ad hoc و زمان کافی و کمی صبر، این باگ می تواند به شما کمک کند که میزان حقوق هر کسی را به دست آورید. مسلما، کاربر Poen در ابتدا مجوز SELECT را نداشته است، اما به یاد داشته باشید که هر یک از کاربران ?Rep می توانند حمله ای این چنینی را پیاده سازی کنند. امیدوارم که در نسخه RTM این مشکل برطرف گردد. مفهوم Inserting invalid rows نکته مهم دیگر در مورد RLS (البته تا نسخه جاری)، این است که مجوز نوشتن توسط سیاست امنیتی مسدود نشده است. بنابراین در صورتی که من بتوانم در جدول سطری درج کنم، ممکن است به طور ناخودآگاه(و یا حتی آگاهانه) رکوردی را برای سایر کاربران ?Rep درج کنم. GRANT INSERT, UPDATE ON dbo.Accounts TO Rep1; GO EXEC('INSERT dbo.Accounts(AccountID,AnnualFees,RepID) VALUES(99,50000,2);') AS USER = N'Rep1'; GO در کد فوق من توانسته ام سطری را درج کنم بدون اینکه بتوانم آن را ببینم. با استفاده از کد زیر می توان این مسئله را بررسی کرد: EXEC('SELECT * FROM dbo.Accounts WHERE AccountID = 99;') AS USER = N'Rep1'; EXEC('SELECT * FROM dbo.Accounts WHERE AccountID = 99;') AS USER = N'Rep2'; GO این مسئله بسیار کوچکیست، ولی جای بررسی بیشتری را دارد. در محیط های بسیار حساس، درج رکوردهایی بجای سایر کاربران، می تواند مشکلات بسیار جدی را ایجاد کند. در حال حاضر، برای ایمن کردن جداول از درج های ناخواسته یا نادرست، باید از Check Constraintها یا INSERT Trigger و یا با کنترل عملیات درج در SPها در جهت رسیدن به منطق استفاده شده در تابع گزاره ای استفاده کنیم. البته تا این نسخه که ما مورد بررسی قرار داده ایم، سایر DMLها محافظت شده هستند. برای مثال، در کد زیر من نمی توانم سطری را که قادر به دیدن آن نیستم، بروزرسانی کرده و یا حذف کنم. EXEC('UPDATE dbo.Accounts SET AnnualFees*=2 WHERE AccountID = 99;') AS USER = N'Rep1'; EXEC('SELECT * FROM dbo.Accounts WHERE AccountID = 99;') AS USER = N'Susan'; GO کدهای تکمیلی CREATE TABLE dbo.AccountReps ( RepID INT, SQLPrincipalName SYSNAME, CONSTRAINT PK_AccountReps PRIMARY KEY(RepID), CONSTRAINT UQ_PrincipalName UNIQUE(SQLPrincipalName) ); GO CREATE USER Rep1 WITHOUT LOGIN; CREATE USER Rep2 WITHOUT LOGIN; CREATE USER Rep3 WITHOUT LOGIN; CREATE USER Peon WITHOUT LOGIN; CREATE USER Susan WITHOUT LOGIN; CREATE ROLE RepManagers; ALTER ROLE RepManagers ADD MEMBER Susan; GO INSERT dbo.AccountReps(RepID, SQLPrincipalName) VALUES(1, N'Rep1'),(2, N'Rep2'),(3, N'Rep3'); GO CREATE TABLE dbo.Accounts ( AccountID INT, AnnualFees INT, RepID INT NOT NULL, CONSTRAINT PK_Accounts PRIMARY KEY(AccountID), CONSTRAINT FK_AccountReps FOREIGN KEY(RepID) REFERENCES dbo.AccountReps(RepID) ); GO INSERT dbo.Accounts(AccountID,AnnualFees,RepID) VALUES (1,55000,1),(2,25000,1),(3,65000,1),(4,35000,2),(5,82000,2); GO GRANT SELECT ON dbo.Accounts TO Peon, Rep1, Rep2, Rep3, Susan; GRANT SELECT ON dbo.AccountReps TO Peon, Rep1, Rep2, Rep3, Susan; GO CREATE USER sqlapp WITHOUT LOGIN; GRANT SELECT ON dbo.Accounts TO sqlapp; GO -------------------------------------------------- CREATE FUNCTION dbo.LimitAccountAccess(@RepID INT) RETURNS TABLE WITH SCHEMABINDING AS RETURN ( SELECT [Go] = 1 FROM dbo.AccountReps WHERE (RepID = @RepID AND SQLPrincipalName = CONVERT(SYSNAME, CONTEXT_INFO()) ) OR IS_MEMBER(N'RepManagers') = 1 ); GO CREATE SECURITY POLICY AccountAndRepPolicy ADD FILTER PREDICATE dbo.LimitAccountAccess(RepID) ON dbo.AccountReps, ADD FILTER PREDICATE dbo.LimitAccountAccess(RepID) ON dbo.Accounts WITH (STATE = ON); GO -------------------------------------------------- EXECUTE AS USER = N'sqlapp'; GO DECLARE @ci VARBINARY(128) = CONVERT(VARBINARY(128),N'Rep1'); SET CONTEXT_INFO @ci; SELECT USER_NAME(), * FROM dbo.Accounts; GO REVERT; GO بررسی میزان تاثیر RLS بر کارایی SQL Server مفهوم Row Level Security، در اینجا قصد نداریم که سناریوی مربوط به تابع گزاره ای و سیاست امنیتی را مورد بررسی قرار دهیم، بلکه فقط می خواهیم با انجام یک آزمایش، کارایی SQL Server را بدون RLS و با استفاده از RLS مقایسه کنیم. کدهای زیر جداول، ایندکس ها و داده های مورد نیاز برای انجام آزمایش را ایجاد می کند: -- Create SampleUser table CREATE TABLE [dbo].[SampleUser]( [UserID] [int] NOT NULL PRIMARY KEY, [Username] [varchar](30) ) GO -- Create SampleData table and foreign key to SampleUser table CREATE TABLE [dbo].[SampleData]( [RowKey] [int] NOT NULL PRIMARY KEY, [CreateDate] [datetime] NOT NULL, [OtherDate] [datetime] NOT NULL, [VarcharColumn] [varchar](20) NULL, [IntColumn] [int] NULL, [FloatColumn] [float] NULL, [UserID] [int] NOT NULL ) GO ALTER TABLE [dbo].[SampleData] WITH CHECK ADD CONSTRAINT [FK_SampleData_SampleUser] FOREIGN KEY([UserID]) REFERENCES [dbo].[SampleUser] ([UserID]) GO -- Load SampleUser table DECLARE @val INT SELECT @val=1 WHILE @val < 51 BEGIN INSERT INTO SampleUser VALUES (@val,'User' + cast(@val AS VARCHAR)) SELECT @val=@val+1 END GO -- Load SampleData table DECLARE @val INT SELECT @val=1 WHILE @val < 5000000 BEGIN INSERT INTO SampleData VALUES (@val, getdate(), DATEADD(DAY, ABS(CHECKSUM(NEWID()) % 365),'2015-01-01'), 'TEST' + cast(round(rand()*100,0) AS VARCHAR), round(rand()*100000,0), round(rand()*10000,2), round(rand()*49,0)+1) SELECT @val=@val+1 END GO -- create indexes CREATE NONCLUSTERED INDEX [IX_SampleData_CreateDate] ON [dbo].[SampleData] ([CreateDate] ASC) GO CREATE NONCLUSTERED INDEX [IX_SampleData_UserID] ON [dbo].[SampleData] ([UserID] ASC) GO CREATE NONCLUSTERED INDEX [IX_SampleUser_Username] ON [dbo].[SampleUser] ([Username] ASC) GO در ادامه، کاربران و مجوزهای آنها را تعریف می کنیم. پیشنهاد میکنیم برای درک بهتر مفاهیم کوئری نویسی را مطالعه کنید. -- sysadmin user CREATE LOGIN [test_sa] WITH PASSWORD=N'#######', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO ALTER SERVER ROLE [sysadmin] ADD MEMBER [test_sa] GO -- regular user CREATE LOGIN [User10] WITH PASSWORD=N'#######', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO USE [TestDB] GO CREATE USER [User10] FOR LOGIN [User10] GO USE [TestDB] GO ALTER ROLE [db_datareader] ADD MEMBER [User10] GO حال، پیش از اینکه RLS را برای این جداول فعال کنیم، پرس و جوهای زیر را برای کاربران مشخص شده اجرا می کنیم و نتایج حاصل شده از اجرای این پرس وجوها در SQL Query Profiler را ثبت می کنیم. -- run using test_sa account -- query 1 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = 'User10' GO -- query 2 SELECT * FROM SampleData d WHERE CreateDate > '2016-02-03 19:59:47.560' -- run using User10 account -- query 3 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = user_name() GO -- query 4 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = user_name() AND CreateDate > '2016-02-03 19:59:47.560' GO سپس، RLS را با تعریف تابع گزاره ای و سیاست امنیتی مورد نظر ایجاد و فعال می کنیم. افراد علاقهمند میتوانند با مطالعه مقاله پرکاربردترین دستورات SQL Server، دانش خود را در زمینه کوئرینویسی گسترش دهند. CREATE FUNCTION dbo.fn_securitypredicateUser (@UserID int) RETURNS TABLE WITH Schemabinding AS RETURN SELECT 1 AS [fn_securitypredicateUser_result] FROM dbo.SampleUser SU WHERE (SU.UserID=@UserID AND SU.Username = user_name()) OR IS_SRVROLEMEMBER(N'sysadmin') = 1 GO CREATE SECURITY POLICY fn_security ADD FILTER preDICATE dbo.fn_securitypredicateUser(UserID) ON dbo.SampleData GO حال، مشابه قبل عمل کرده و پرس و جوهای زیر را دوباره و پس از فعال شدن RLS اجرا کرده و نتایج حاصل شده از اجرای این پرس وجوها در برنامه SQL Query Profiler را ثبت می کنیم. -- run using test_sa account -- query 1 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = 'User10' GO -- query 2 SELECT * FROM SampleData d WHERE CreateDate > '2016-02-03 19:59:47.560' -- run using User10 account -- query 3 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = user_name() GO -- query 4 SELECT * FROM SampleData d INNER JOIN SampleUser u on d.UserID=u.UserID WHERE u.Username = user_name() AND CreateDate > '2016-02-03 19:59:47.560' GO در جدول زیر نتایج به دست آمده از اجرای پرس و جوهای فوق برای دو کاربر test_sa و User10 در دو حالتی که RLS فعال و غیر فعال است، نشان داده شده است. اگر به آمار کاربری که دارای مجوز sysadmin است(کاربر test_sa و پرسوجوهای ۱ و ۲) نگاه کنیم، صرف نظر از اینکه RLS فعال است یا خیر، تفاوت بیشتر در میزان CPU مصرفی می باشد. البته در محیط های واقعی، کاربر با مجوز sysadmin کمتر مورد استفاده قرار می گیرد. اگر به آمار کاربر عادی(کاربر User10 و پرسوجوهای ۳ و ۴) نگاه کنیم، نتایج کمی متفاوت است. در پرسوجوی ۳، میزان CPU مصرفی و زمان اجرا و تعداد عملیات خواندن دارای تفاوت چشم گیری هستند. علت این موضوع این است که با فعال بودن RLS، تابع گزاره ای به ازای تک تک سطرهای جدول اجرا می شود و این یعنی اسکن کردن تمامی جدول (البته معمولا این گونه پرسوجو ها از طرف برنامه کاربردی کمتر صادر می شوند). پرسوجوی چهام یک پرسوجوی استاندارد است که معمولا از طرف برنامه کاربردی تقاضا می شود (پرسوجوی SELECT به همراه عبارت WHERE). همانطور که مشخص است در این پرسوجو نیز یک سربار اضافه به علت اجرا شدن تابع گزاره ای برای سطرهای خروجی وجود دارد. سخن پایانی مفهوم Row Level Security، در نهایت می توان نتیجه گرفت که این قابلیت جدید، از این نظر که کنترل دسترسی به داده ها را می توان به سادگی و بدون هر گونه تغییری در پرسوجوهای جاری و برنامه کاربردی و حتی بدون اینکه کاربر اطلاعی از آن داشته باشد اعمال کرد، می تواند بسیار مفید باشد. ولی در کنار منافع به دست آمده، مسئله اصلی، میزان سربار اضافه ای است که این قابلیت جدید به بانک اطلاعاتی ما ممکن است تحمیل نماید. ما در نیک آموز منتظر نظرات ارزشمند شما درباره این مقاله هستیم. چه رتبه ای میدهید؟ میانگین ۵ / ۵. از مجموع ۱ اولین نفر باش معرفی نویسنده مقالات 11 مقاله توسط این نویسنده محصولات 0 دوره توسط این نویسنده سید محمد حسینی معرفی محصول مسعود طاهری دوره آموزش امنیت در SQL Server 2022 7.000.000 تومان مقالات مرتبط ۰۲ آبان SQL Server ابزار Database Engine Tuning Advisor؛ مزایا، کاربردها و روش استفاده تیم فنی نیک آموز ۱۵ مهر SQL Server معرفی Performance Monitor ابزار مانیتورینگ SQL Server تیم فنی نیک آموز ۱۱ مهر SQL Server راهنمای جامع مانیتورینگ بکاپ ها در SQL Server تیم فنی نیک آموز ۰۸ مهر SQL Server Resource Governor چیست؟ آشنایی با نحوه پیکربندی و اهمیت های آن تیم فنی نیک آموز دیدگاه کاربران لغو پاسخ دیدگاه نام و نام خانوادگی ایمیل ذخیره نام، ایمیل و وبسایت من در مرورگر برای زمانی که دوباره دیدگاهی مینویسم. موبایل برای اطلاع از پاسخ لطفاً مرا با خبر کن ثبت دیدگاه Δ