Execute As与连接池结合使用的测试

简介

    在SQL Server中,Execute As关键字允许当前账户在特定上下文中以另一个用户或登录名的身份执行SQL语句,比如用户张三有权限访问订单表,用户李四并没有权限访问订单表,那么给予用户李四访问订单的表的权限就有些过头了,因为李四可能只有在很特定的上下文环境中才需要访问订单表,因此可以在特定上下文中使用Execute As Login 张三,暂时以张三的身份访问订单表,从而保证更安全的权限控制。

    另一方面,应用程序通过网络与数据库连接是需要在传输层通过TCP协议,而TCP协议在建立连接的阶段的成本会比较高(1.同步请求 2同步请求+Ack 3.确认 这三个阶段),因此减少TCP连接可以很大程度上提升性能。因此当应用程序与数据库建立连接后,在一定空闲时间内不在TCP协议上切断连接,而是保持连接,连接的断开操作仅仅是逻辑上断开,当新的请求由应用程序发送到客户端时,复用之前建立在应用程序与数据库上的连接,从而极大的提升了连接性能。

    当在连接池上使用Execute As切换连接的安全上下文时则可能产生的情况我们通过下述几种实验来得出结论。

 

在使用连接池的情况下使用Execute As切换安全上下文

    试验中所用的连接字符串全部为:

   1: data source=.;database=test;uid=GetMembers;pwd=sa;pooling=true;Connection Timeout=30
   2:  
   3:  

实验一:使用动态SQL,切换安全上下文

    该实验分别使用两个连接,第一次连接中,用户为GetMembers,将安全上下文切换为系统最大权限登录名SA,连接断开时保持SA安全上下文,应用程序端发送的SQL代码如代码1:

   1: EXECUTE AS LOGIN = ‘sa‘;SELECT * FROM dbo.Higher;"

   代码1.第一次连接数据库执行的语句

 

    在将身份切换为SA后,正常查询GetMembers没有的dbo.Higher表的权限,执行完代码1所示的SQL后,连接正常关闭。第二次连接使用连接池复用第一次连接所建立的连接,执行的SQL如代码2:

   1: SELECT * FROM Higher

代码2.第二次连接使用的SQL

   

    在Asp.net端看到的查询结果如图1所示。

   

    图1.两次连接在Asp.net中的信息

 

    由图1可以看出,当复用连接池时,由于第一次连接以GetMembers登录名登录,安全上下文切换到SA并没有切换回来,第二次再次登录时就会报错,报的错对应在SQL Server日志里如图2所示。

  

    图2.SQL Server端报错

 

    结论:由此看出,当连接池复用时,第一次连接切换了上下文第二次连接复用时就会直接报错,这也是期待的结果,从而保证了安全性,如果希望采用这种方式结合连接池,则必须在第一次连接完使用Revert将安全上下文转换回登录时的安全上下文。

 

实验二:在存储过程中使用Execute As转换安全上下文

    还是两次连续的连接,第一次在存储过程中执行Execute As转换上下文为SA,代码如代码3所示:

   1: CREATE PROCEDURE [dbo].[GetMembers]
   2:  
   3: AS
   4:  
   5: EXECUTE AS USER = ‘sa‘

代码3.在存储过程中执行Execute As

 

    第二次连接进来的查询执行一个非常简单的Select语句,但没有对应权限,执行结果如图3所示:

图3.第二次连接不会受第一次在存储过程中改变上下文的影响

 

    在数据库端对应的跟踪如图4所示。

   

    图4.对应的跟踪

 

    因此可以看出,在存储过程中改变安全上下文对连接池无影响,安全上下文仅仅在存储过程中有效。

 

实验三:连接池对隔离级别的影响

    在实验3中对连接的默认隔离级别更改,更改为可序列化级别,SQL语句如代码4所示。

   1: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

代码4.改变连接的隔离级别

 

    随后的连接查询并返回当前连接的隔离级别,结果如图5所示。

   

    图5.改变隔离级别导致复用连接池中的连接隔离级别改变

 

    结论:使用连接池对修改Session级别的隔离级别用完必须改回默认连接,否则可能导致后续连接在不正确的隔离级别下运行。

 

实验四:在存储过程中改变隔离级别的连接复用的影响

    下面我们在存储过程中改变隔离级别,代码如代码5所示:

   1: create PROCEDURE [dbo].[TestIslation]
   2: AS
   3:  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
   4:  
   5:  SELECT CASE transaction_isolation_level 
   6: WHEN 0 THEN ‘Unspecified‘ 
   7: WHEN 1 THEN ‘ReadUncommitted‘ 
   8: WHEN 2 THEN ‘ReadCommitted‘ 
   9: WHEN 3 THEN ‘Repeatable‘ 
  10: WHEN 4 THEN ‘Serializable‘ 
  11: WHEN 5 THEN ‘Snapshot‘ END AS TRANSACTION_ISOLATION_LEVEL 
  12: FROM sys.dm_exec_sessions 
  13: where session_id = @@SPID

代码5.在存储过程中更改隔离级别,并显示当前的隔离级别

 

    在随后的连接中,在非存储过程中调用显示当前Session隔离级别的语句,并打印,结果如图6所示。

    图6.

 

    由图6可以看出,第三次连接在存储过程内改变隔离级别,第四次连接的隔离级别并不受影响。

 

   结论:在存储过程内改变隔离级别不会影响后续连接池的使用。

 

 

小结

    本文对在使用连接池情况下数据库中的一些细节场景进行了实验,可以看到对于连接池复用来说,改变隔离级别可能会存在隐性的风险,其他情况SQL Server都能够显式处理。因此使用连接池对修改Session级别的隔离级别用完必须改回默认连接,或者在语句级别修改隔离等级而不是Session级别。

时间: 2024-11-05 15:17:37

Execute As与连接池结合使用的测试的相关文章

SQL Server的Execute As与连接池结合使用的测试

原文:SQL Server的Execute As与连接池结合使用的测试 简介     在SQL Server中,Execute As关键字允许当前账户在特定上下文中以另一个用户或登录名的身份执行SQL语句,比如用户张三有权限访问订单表,用户李四并没有权限访问订单表,那么给予用户李四访问订单的表的权限就有些过头了,因为李四可能只有在很特定的上下文环境中才需要访问订单表,因此可以在特定上下文中使用Execute As Login 张三,暂时以张三的身份访问订单表,从而保证更安全的权限控制.    

几个主流的Java连接池整理

池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对象的容器,在进程初始化时创建一定数量的对象.需要时直接从池中取出一个空闲对象,用完后并不直接释放掉对象,而是再放到对象池中以方便下一次对象请求可以直接复用.其他几种池的设计思想也是如此,池技术的优势是,可以消除对象创建所带来的延迟,从而提高系统的性能. 要了解Java连接池我们先要了解数据库连接池(

.Net连接字符串设置连接池大小显著提高数据库速度

在访问mysql数据库时,如果在连接字符串中设置使用连接池,同时设置连接池大小,经测试,可以显著提高访问数据库时的速度. 连接字符串: connectionStrings>    <add name="connectionstr" connectionString="Database=userDB;Data Source=localhost;User Id=root;Password=abcabc;CharSet=utf8;port=3306;Pooling=tr

连接池配置 - tomcat7

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个 应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正是针对这个问题提出来的. 数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而再不是重新建立一个:释放空闲时 间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏.这项技术能明显提高对数据库操作的性能. 数据库连接池在初始化时将创建一定数量的数据库连

[JavaEE] Hibernate连接池配置测试

转载自51CTO http://developer.51cto.com/art/200906/129914.htm Hibernate支持第三方的连接池,官方推荐的连接池是C3P0,Proxool,以及DBCP.在Hibernate连接池配置时需要注意的有三点: 一.Apche的DBCP在Hibernate2中受支持,但在Hibernate3中已经不再推荐使用,官方的解释是这个连接池存在缺陷.如果你因为某种原因需要在Hibernate3中使用DBCP,建议采用JNDI方式. 二.默认情况下(即没

几个主流java连接池

池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对象的容器,在进程初始化时创建一定数量的对象.需要时直接从池中取出一个空闲对象,用完后并不直接释放掉对象,而是再放到对象池中以方便下一次对象请求可以直接复用.其他几种池的设计思想也是如此,池技术的优势是,可以消除对象创建所带来的延迟,从而提高系统的性能. 要了解Java连接池我们先要了解数据库连接池(

Hibernate三种连接池对比

1.C3P0 有评论说它的算法不是最优的,在同一项目中分别用了几个常用的Hibernate连接池配置,然后测试其性能,发现c3p0占用资源比较大,效率也不高; 2.DBCP 由于在Hibernate3.0中,已经不再支持dbcp了,Hibernate的作者在hibernate.org中,明确指出在实践中发现dbcp有 BUG,在某些种情会产生很多空连接不能释放,所以抛弃了对dbcp的支持,所有慎重使用 3.Proxool proxool不少行家推荐使用,而且暂时来说,是负面评价是最少的一个 原文

redis mysql 连接池 之 golang 实现

分享一下 golang 实现的 redis 和 mysql 连接池,可以在项目中直接引用连接池句柄,调用对应的方法. 举个栗子: 1 mysql 连接池的使用 (1) 在项目子目录放置 mysql.go (2)在需要调用的地方导入连接池句柄 DB (3)调用 DB.Query() 2 redis 连接池的使用 (1)在项目子目录放置 redis.go (2)在需要调用的地方导入连接池句柄 Cache (3)调用 Cache.SetString ("test_key", "te

poco c++框架库应用:数据库的连接池

Poco c++中的数据库驱动部分,简洁,干净,工整,和数据库连接,封装成这样,还是比较好用的.下面是连接MySQL连接的方法. 一 需求说明 与MySQL数据库建立连接池,并在连接池中获得一个连接,实现数据库常用增删改查 二 目标说明 写出ANSI风格的代码,并输出高度结果到终端,验证程序的有效性 三 调试条件: 1.系统:ubuntu 2.qt 或 其它IDE 3.安装了mysql,有正确的访问账户和密码 四 例程说明 使用IDE:Qt Creator 项目文件:pocomysql.pro