sql 如何设置行级锁

SQL Server 2016 came with many new features and enhancements for existing ones, that concentrate on the aspect of SQL Server security. One of the new security features introduced in SQL Server 2016 is Row-Level Security. This feature allows us to control access deeply into the rows level in the database table, based on the user executing the query. This is done within the database layer, in complete transparency to the application process, without the need to manage it with complex coding at the application layer.

SQL Server 2016附带了许多新功能和增强功能,这些功能和增强功能集中在SQL Server安全性方面。 SQL Server 2016中引入的新安全功能之一是行级安全性 。 此功能使我们可以根据执行查询的用户来控制对数据库表中行级别的深入访问。 这是在数据库层内完成的,对应用程序过程完全透明,而无需在应用程序层使用复杂的代码进行管理。

Row-Level Security (RLS) provides us with a way to restrict users to allow them to work only with the data they have access to. For example, each courier in a shipping company can access only the data related to the shipments he is requested to deliver, without being able to access other courier’s data. Each time data access is performed from any tier, data access will be restricted by the SQL Server Engine, reducing the security system surface area.

行级安全性(RLS)为我们提供了一种限制用户的方法,以允许他们仅使用他们有权访问的数据。 例如,运输公司中的每个快递员只能访问与他要交付的货物有关的数据,而不能访问其他快递员的数据。 每次从任何层执行数据访问时,数据访问都会受到SQL Server Engine的限制,从而减小了安全系统的表面积。

There are two types of security predicates that are supported in Row-Level Security; the Filter predicate that filters row silently for read operations. The Silent filter predicate means that the application will not be made aware that the data is filtered, null values will be returned if all rows are filtered, without raising an error message. The Block predicate prevents any write operation that violates any defined predicate with an error message returned as a result of the block. This policy can be turned ON and OFF with four main blocking types; AFTER INSERT and AFTER UPDATE blocking will prevent the users from updating the rows to values that will violate the predicate. BEFORE UPDATE will prevent the users from updating the rows that are violating the predicate currently. BEFORE DELETE will prevent the users from deleting the rows. Trying to add a predicate on a table that already has a predicate defined will result with error.

行级安全性支持两种类型的安全性谓词: 用于对读操作进行静默过滤的Filter谓词 。 Silent过滤器谓词意味着不会使应用程序知道数据已被过滤,如果所有行都被过滤,则将返回空值,而不会引发错误消息。 块谓词可防止任何写操作违反任何定义的谓词,并会由于该块而返回错误消息。 可以使用四种主要的阻止类型来打开和关闭此策略。 AFTER INSERTAFTER UPDATE阻止将阻止用户将行更新为违反谓词的值。 “更新前”将阻止用户更新当前违反谓词的行。 删除前将阻止用户删除行。 尝试在已定义谓词的表上添加谓词将导致错误。

Data access restriction using Row-Level Security is accomplished by defining a Security predicate as an inline-table-valued function that will restrict the rows based on filtering logic, which is invoked and enforced by a Security Policy created using the CREATE SECURITY POLICY T-SQL statement and working as predicates container. SQL Server allows you to define multiple active security policies but without overlapping predicates. Altering a table with a schema bound security policy defined on it will fail with error.

使用行级安全性进行数据访问限制是通过将安全性谓词定义为一个内联表值函数来实现的,该函数将根据过滤逻辑来限制行,该过滤逻辑由使用CREATE SECURITY POLICY T-创建的安全策略调用和强制执行SQL语句并作为谓词容器。 SQL Server允许您定义多个活动的安全策略,但没有重叠的谓词。 更改具有定义的架构绑定安全策略的表将失败,并显示错误。

As in any new feature, SQL Server Row-Level Security has a number of limitations, such as the fact that Filestream and Polybase features are not compatible with the feature. Although you are able to create a view over a table with Row-Level Security configured on it, you are not able to create an indexed view on that view. It is not recommended to configure Change Data Capture, Change tracking and/or Temporal Tables on a table with Row-Level Security due to fact that critical data may be available in the tables containing the data changes or the history tables and will be accessible by all users that deal with these tables to get the latest changes. The blocked predicate is not compatible with partitioned views, but it can be used with the filter predicate. Another thing is that RLS is implemented using a function, which may lead to that situation when the optimized, any queries that use the Columnstore indexes may be re-written, resulting in the batch mode not being used.

与任何新功能一样,SQL Server行级安全性有许多限制,例如Filestream和Polybase功能与该功能不兼容。 尽管您可以在配置了行级安全性的表上创建视图,但是无法在该视图上创建索引视图。 不建议在具有行级安全性的表上配置“更改数据捕获”,“更改跟踪”和/或“时态表”,因为事实是关键数据可能在包含数据更改或历史记录表的表中可用,并且可以通过以下方式访问:处理这些表以获取最新更改的所有用户。 被阻止的谓词与分区视图不兼容,但是可以与过滤器谓词一起使用。 另一件事是RLS是使用函数实现的,当使用Columnstore索引进行优化的任何查询都可能被重写时,可能导致这种情况,从而导致不使用批处理模式。

Let’s start our demo to understand how the Row-Level Security feature works in a practical sense. We will start by creating a demo table that will hosts the couriers’ shipments information, on which we will configure Row-Level Security:

让我们开始演示,以实际了解行级安全功能的工作方式。 我们将从创建一个演示表开始,该表将托管信使的发货信息,在此我们将配置行级安全性:


USE [SQLShackDemo]
GO
CREATE TABLE [dbo].[Courier_Shipments]([ID] [int] IDENTITY(1,1) NOT NULL,[Courier_Name] [varchar](10) NULL,[NumOfShipmentsInPackage] [int] NULL,[Package_Date] [datetime] NULL,[Package_Cost] [int] NULL,[Package_City] [varchar](10) NULL,CONSTRAINT [PK_Courier_Shipments] PRIMARY KEY CLUSTERED
([ID] ASC
)) ON [PRIMARY]GO

Once the table is created successfully, let’s insert few rows on that table, for example, we will insert two records for each courier as below:

成功创建表格后,让我们在该表格上插入几行,例如,我们将为每个快递员插入两条记录,如下所示:


USE [SQLShackDemo]
GO
INSERT INTO [dbo].[Courier_Shipments]([Courier_Name],[NumOfShipmentsInPackage],[Package_Date],[Package_Cost],[Package_City])VALUES('John',5,'2016-09-22 01:35:00:000',580,'LON'),('Ghezil',3,'2016-09-22 03:45:00:000',470,'LAX'),('Mark',2,'2016-09-22 04:32:00:000',118,'JFK'),('Ghezil',5,'2016-09-22 02:38:00:000',358,'LAX'),('Mark',4,'2016-09-22 06:12:00:000',774,'JFK'),('John',7,'2016-09-22 08:07:00:000',941,'LON')
GO

Also we will create a three users, one for each courier who will retrieve his shipments data:

另外,我们将创建三个用户,每个快递员一个,他将检索其货运数据:


CREATE USER John WITHOUT LOGIN;
CREATE USER Ghezil WITHOUT LOGIN;
CREATE USER Mark WITHOUT LOGIN;   

And grant SELECT access on the Courier_Shipments table for the newly created three users:

并在Courier_Shipments表上为新创建的三个用户授予SELECT访问权限:


GRANT SELECT ON [Courier_Shipments] TO John;
GRANT SELECT ON [Courier_Shipments] TO Ghezil;
GRANT SELECT ON [Courier_Shipments] TO Mark;

It is highly recommended to create a separate schema for the Row-Level Security database objects:

强烈建议为行级安全性数据库对象创建一个单独的架构:


CREATE SCHEMA RLS;
GO

Till this step, the table and the new schema is ready to start configuring the Row-Level Security feature. First we will create the Filter Predicate function that depends on the logged in user name to filter the users and check their access on the data as follows:

到此步骤为止,表和新架构已准备就绪,可以开始配置行级安全性功能。 首先,我们将创建Filter Predicate函数,该函数取决于已登录的用户名来过滤用户并检查其对数据的访问,如下所示:


CREATE FUNCTION RLS.fn_SecureCourierData(@CourierName AS sysname)  RETURNS TABLE
WITH SCHEMABINDING
AS  RETURN SELECT 1 AS 'SecureCourierShipments'
WHERE @CourierName = USER_NAME();  

And create the Security Policy on the Courier_Shipments table using the previously created predicate function, then turn it on:

然后使用先前创建的谓词函数在Courier_Shipments表上创建安全策略,然后将其打开:


CREATE SECURITY POLICY CourierShipments
ADD FILTER PREDICATE RLS.fn_SecureCourierData(Courier_Name)
ON dbo.Courier_Shipments
WITH (STATE = ON);   

Now, Row-Level Security is fully configured and ready to start filtering any new data access on the Courier_Shipments table. Expanding the Security node of the SQLShackDemo database, the newly created Security Policy can be found as in the following image using the SQL Server Management Studio:

现在,已完全配置行级安全性,并准备开始过滤Courier_Shipments表上的所有新数据访问。 展开SQLShackDemo数据库的“安全性”节点,可以使用SQL Server Management Studio在下图中找到新创建的“安全策略”:

If we try to run the below query using John user:

如果我们尝试使用John用户运行以下查询:


EXECUTE AS USER = 'John';
SELECT * FROM Courier_Shipments;
REVERT;

The following result will show us that the query executed by John will return only the two records related to John’s shipments:

以下结果将向我们显示,约翰执行的查询将仅返回与约翰的发货有关的两条记录:

The same thing will occur with Ghezil, if he tries to run the below SELECT statement with his user:

如果Ghezil尝试与他的用户一起运行下面的SELECT语句,则将发生同样的事情:


EXECUTE AS USER = 'Ghezil';
SELECT * FROM Courier_Shipments;
REVERT;  

The two records related to him will be retrieved only:

与他相关的两条记录将仅被检索:

The third courier also, Mark, who will retrieve only the rows related to his shipments when he run the below query:

第三名快递员Mark,在运行以下查询时将仅检索与其货运相关的行:


EXECUTE AS USER = 'Mark';
SELECT * FROM Courier_Shipments;
REVERT;

The results the Mark will see:

Mark将看到的结果:

It is clear from the previous results that the Row-Level Security feature can be used to filter the data that each user can see depending on the filtering criteria defined in the predicate function.

从先前的结果可以明显看出,可以根据谓词函数中定义的过滤条件,使用行级安全性功能过滤每个用户可以看到的数据。

If you manage to stop using the Row-Level Security feature that we configured, you need to disable the Security Policy using the ALTER SECURITY POLICY statement below:

如果您设法停止使用我们配置的行级安全功能,则需要使用下面的ALTER SECURITY POLICY语句禁用安全策略:


Alter Security Policy CourierShipments  with (State = off)

Then drop that Security Policy and the Filter Predicate function as follows:

然后删除该安全策略和筛选谓词功能,如下所示:


Drop Security Policy CourierShipments
Drop Function RLS.fn_SecureCourierData

Now the Row-Level Security is removed completely from the Courier_Shipments table.

现在,从Courier_Shipments表中完全删除了行级安全性。

As we mentioned previously, there is another type of predicates that can be used in the Row-level Security feature which is the Block Predicate. Let’s have a second demo to know how the block predicate can be configured and work.

如前所述,行级安全性功能中可以使用另一种谓词,即块谓词。 让我们进行第二个演示,以了解如何配置块谓词并使其工作。

Again, we will create a predicate function that will filter the data access depends on the users connecting to that table as follows:

同样,我们将创建一个谓词函数,该函数将过滤数据访问,具体取决于连接到该表的用户,如下所示:


CREATE FUNCTION RLS.fn_SecureCourierData (@Courier_Name sysname)RETURNS TABLEWITH SCHEMABINDING
ASRETURN SELECT 1 AS fn_SecureCourierData_resultWHERE @Courier_Name= user_name()
GO

Also we will create the security policy, but this time it will contain an AFTER INSERT block predicate condition in addition to the filter predicate:

我们还将创建安全策略,但是这次除了过滤谓词外,它还将包含AFTER INSERT块谓词条件:


CREATE SECURITY POLICY dbo.fn_Courier_ShipmentsADD FILTER PREDICATE RLS.fn_SecureCourierData(Courier_Name)  ON  dbo.Courier_Shipments,ADD BLOCK PREDICATE RLS.fn_SecureCourierData(Courier_Name)  ON  dbo.Courier_Shipments AFTER INSERT
GO

And enable the Security policy as follows:

并启用安全策略,如下所示:


Alter Security Policy fn_Courier_Shipments  with (State = ON)

As the blocking will be on the INSERT operation, we will grant Mark user access to do so:

由于将对INSERT操作进行阻止,因此我们将授予Mark用户访问权限:


GRANT SELECT, INSERT, UPDATE, DELETE ON Courier_Shipments TO Mark;

If Mark tries to apply the below SELECT statement with his user:

如果Mark尝试对其用户应用以下SELECT语句:


EXECUTE AS USER = 'Mark';
SELECT * FROM Courier_Shipments;
REVERT;

We will see the same previous result, where he will be able to see the records related to his shipments only:

我们将看到相同的先前结果,在该结果中,他将只能看到与他的发货有关的记录:

But if he tries to insert a new record with his user, but with the courier name different from his name, let’s say John:

但是,如果他尝试与他的用户一起插入新记录,但快递员名称与他的名字不同,那么可以说约翰:


EXECUTE AS USER = 'Mark';
INSERT INTO [dbo].[Courier_Shipments]([Courier_Name],[NumOfShipmentsInPackage],[Package_Date],[Package_Cost],[Package_City])VALUES('John',5,'2016-09-22 01:35:00:000',580,'LON')REVERT;

He will receive an error message indicates that the INSERT process is blocked on the Courier_Shipments table using the block predicate, as he is trying to insert a new record not related to his name as follows:

他将收到一条错误消息,指示使用块谓词在Courier_Shipments表上阻止了INSERT进程,因为他试图插入与他的名字无关的新记录,如下所示:

Again, if the previous insert statement is modified by replacing John name with Mark name and execute it with Mark’s user:

同样,如果通过将John名称替换为Mark name修改了先前的insert语句,并由Mark的用户执行了该语句:


EXECUTE AS USER = 'Mark';
INSERT INTO [dbo].[Courier_Shipments]([Courier_Name],[NumOfShipmentsInPackage],[Package_Date],[Package_Cost],[Package_City])VALUES('Mark',5,'2016-09-22 01:35:00:000',580,'LON')

The new row will be inserted successfully:

新行将成功插入:

Which is clear from running the SELECT statement with his user, showing the below result:

与他的用户一起运行SELECT语句可以很清楚地看到以下结果:

As you can conclude from the previous result, the Row-level Security feature can be also used to block the user from applying specific operations on the rows that he has no access on it.

从上一个结果可以得出结论,行级安全性功能还可以用于阻止用户对无法访问的行执行特定操作。

New system objects have also been introduced in SQL Server 2016 to query the Row-Level Security feature’s information. The sys.security_policies can be used to retrieve all information about the defined security policy on your database as below:

SQL Server 2016中还引入了新的系统对象,以查询行级安全性功能的信息。 可以使用sys.security_policies检索有关数据库上已定义的安全策略的所有信息,如下所示:


SELECT name,type_desc ,create_date ,modify_date,is_enabled,is_schema_bound  FROM sys.security_policies

The result in our case will be like:

在我们的案例中,结果将是:

The sys.security_predicates system object also can be used to retrieve all predicates; filter and block predicates defined within the security policy as follows:

sys.security_predicates系统对象还可以用于检索所有谓词;例如: 过滤和阻止在安全策略中定义的谓词,如下所示:


SELECT * FROM sys.security_predicates

The security policy predicates in our demo will be like:

我们的演示中的安全策略谓词将类似于:

A common question that you may ask or may be asked, is if there any performance impact or side effect when using the Row-Level Security feature? The suitable answer here is that it depends. Yes, it depends on the complexity of the predicate logic you define, as it will be checked for each data access in your table. If you define a simple direct predicate filter, you will not notice any overhead or performance degradation in your database.

您可能会问或可能会问的一个常见问题是,使用行级安全性功能是否会对性能产生影响或产生副作用? 这里合适的答案是取决于情况。 是的,这取决于您定义的谓词逻辑的复杂性,因为将对表中的每个数据访问进行检查。 如果定义简单的直接谓词过滤器,则不会在数据库中发现任何开销或性能下降。

结论 (Conclusion)

SQL Server 2016 comes with many useful features that make our life easier. One of these features is the Row-Level Security feature that is used to secure the access on the database at the row level, by filtering the data that the user has no access to and allow him/her to work only on the rows he/she has access to. Row-Level Security also enables users to block specific operations by preventing the user from inserting, updating or deleting the data he/she doesn’t have to. You can easily add the predicates and filtering criteria that fit your situation, but complex predicates will degrade the database performance as this predicate will be checked each time a data access is performed. The most important advice here is to test this feature and your custom configurations on a test environment first before applying it to the production environment in order to be in the safe side.

SQL Server 2016附带了许多有用的功能,这些功能使我们的生活更轻松。 这些功能之一是行级安全性功能,该功能用于通过过滤用户无权访问的数据并仅允许他/她在他/她的行上工作来保护行级对数据库的访问她有权使用。 行级安全性还使用户能够阻止用户插入,更新或删除不需要的数据,从而阻止特定操作。 您可以轻松添加适合您情况的谓词和过滤条件,但是复杂的谓词将降低数据库性能,因为每次执行数据访问时都会检查该谓词。 这里最重要的建议是在将其应用于生产环境之前,首先在测试环境中测试此功能和自定义配置,以确保安全。

看更多 (See more)

To audit all SQL database and security activities, consider ApexSQL Audit, an enterprise level SQL Server auditing tool.

要审核所有SQL数据库和安全活动,请考虑ApexSQL Audit ,这是企业级SQL Server审核工具。

有用的链接 (Useful links)

  • Row-Level Security 行级安全
  • Row Level Security with SQL Server 2016 SQL Server 2016的行级安全性
  • SQL Server 2016 Row Level Security SQL Server 2016行级安全性

翻译自: https://www.sqlshack.com/filter-block-data-access-using-sql-server-2016-row-level-security/

sql 如何设置行级锁

sql 如何设置行级锁_如何使用SQL Server 2016行级安全性过滤和阻止数据访问相关推荐

  1. mysql慢查询 表级锁_三分钟了解Mysql的表级锁——《深究Mysql锁》

    延伸阅读: 五分钟了解Mysql的行级锁 一分钟深入Mysql的意向锁 mysql锁相关讲解及其应用--<深究mysql锁>了解锁前,一定要先看这篇,了解什么是MVCC,如果我们学习锁,没 ...

  2. mysql数据库的行级锁有几种_MySQL中的行级锁、表级锁、页级锁

    在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM ...

  3. mysql是表级锁还是行级锁_带你了解MySQL数据库中的全局锁、表级锁、行级锁

    在 MySQL 数据库中,有很多各种各样的锁,这些锁大致可以分为三类:全局锁.表级锁.行级锁.这篇文章小编就带你简单了解一下这三种锁. 1. 全局锁 全局锁是粒度比较大的锁,基本上也使用不上,就像我们 ...

  4. sql 多表多行模糊查询_从零开始学习SQL(五)多表查询

    经过之前的学习,现在我们已经对查询有了一定的了解,但是我们目前的所有查询都只能找到在一张表中的数据,但如果我们需要寻找分布在多张表格中的数据时,这种之前的查询就做不到了,这时就需要引入一种新的查询方法 ...

  5. SQL Server 2016 行级别权限控制

    背景 假如我们有关键数据存储在一个表里面,比如人员表中包含员工.部门和薪水信息.只允许用户访问各自部门的信息,但是不能访问其他部门.一般我们都是在程序端实现这个功能,而在sqlserver2016以后 ...

  6. sql查询非11位非数字_非生产环境SQL查询性能调优技巧

    sql查询非11位非数字 It is a common misconception that you need real production data, or production like dat ...

  7. oracle临时表经常被锁_这是一篇长篇入门级数据库讲解:oracle数据库数据导入导出步骤

    正如标题一样,本文内容主要介绍了浅谈入门级oracle数据库数据导入导出步骤,文章通过步骤解析介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧!!! ...

  8. sql执行组件是灰色的_如何分析SQL执行计划图形组件

    sql执行组件是灰色的 In the previous articles of this series, SQL Server Execution Plans overview and SQL Ser ...

  9. nessus 命令行新建用户_【笔记3】命令行基础

    命令行基础&为什么要学? 1. 命令行是啥: - 用户通过键盘输入字符指令.计算机输出字符结果的一种人机交互的方式 - 只能输入命令,没有对话框,没有按钮,全部都是文字 - 世界上第一个程序员 ...

最新文章

  1. php artisan常用方法
  2. 二极管参数中英文对照表
  3. spacevim 添加自动折行
  4. python如何读写文件-Python之写入文件(1)
  5. ASP 三十条精华代码
  6. 【Centos】更新为北京时间
  7. oracle tochar fm,oracle的to_char中的fm
  8. 方立勋_30天掌握JavaWeb_Servlet
  9. 说真的,程序员相亲,真的太太太太太太难了 | IT巨能唠
  10. opensuse ati 显卡驱动安装
  11. Linux 命令(76)—— kill 命令
  12. ubuntu14.04LTS 安装后几个基本设置
  13. k2p—b1版本刷固件遇到的问题
  14. 压缩word文档大小的方法?
  15. python学习笔记(07)---(内置容器-字典)
  16. loadrunner录制网页脚本时打不开或打开慢
  17. window 相关dll文件下载
  18. 光伏逆变simlink仿真(MPPT) 最大功率点追踪算法(MPPT)仿真模型,本设计基于扰动观察法(PO)最大功率点跟踪算法追踪光伏电池的发电曲线
  19. 所谓“尽人事,听天命”
  20. Navicat Premium 12 安装使用

热门文章

  1. python中texttable库显示实时数据_python显示数据库数据
  2. 蜘蛛日志分析工具_如何分析蜘蛛日志?
  3. 20165227朱越 预备作业3 Linux安装及学习
  4. Windows phone 8 学习笔记(7) 设备
  5. Access 中数据库操作时提示from子句语法错误
  6. [当当网,你意欲何为]之二:无奈,配送之痛
  7. Linux---文件、软链接于硬链接文件
  8. 【Express】—get根据不同的参数返回不同的数据
  9. 零基础带你学习MySQL—加密函数和系统函数(十六)
  10. JavaScript学习(五十二)—继承、call方法和apply方法