相关疑难解决方法(0)

SQL Server:池化连接中的隔离级别泄漏

正如先前的Stack Overflow问题(TransactionScope和连接池以及SqlConnection如何管理IsolationLevel?)所证明的那样,事务隔离级别在SQL Server和ADO.NET(也是System.Transactions和EF)的池化连接中泄漏,因为它们建立在ADO.NET).

这意味着,在任何应用程序中都可能发生以下危险事件序列:

  1. 发生请求,需要显式事务以确保数据一致性
  2. 任何其他请求都不会使用显式事务,因为它只进行非关键的读取.此请求现在将作为可序列化执行,可能导致危险的阻塞和死锁

问题:防止这种情况的最佳方法是什么?现在到处都需要使用显式交易吗?

这是一个独立的复制品.您将看到第三个查询将继承第二个查询中的Serializable级别.

class Program
{
    static void Main(string[] args)
    {
        RunTest(null);
        RunTest(IsolationLevel.Serializable);
        RunTest(null);
        Console.ReadKey();
    }

    static void RunTest(IsolationLevel? isolationLevel)
    {
        using (var tran = isolationLevel == null ? null : new TransactionScope(0, new TransactionOptions() { IsolationLevel = isolationLevel.Value }))
        using (var conn = new SqlConnection("Data Source=(local); Integrated Security=true; Initial Catalog=master;"))
        {
            conn.Open();

            var cmd = new SqlCommand(@"
select         
        case transaction_isolation_level 
            WHEN 0 THEN 'Unspecified' 
            WHEN 1 THEN …
Run Code Online (Sandbox Code Playgroud)

t-sql sql-server ado.net transactions transactionscope

53
推荐指数
3
解决办法
9465
查看次数

sp_reset_connection有什么作用?

sp_reset_connection似乎由SQL Server连接池调用,以确保从池中重用的连接重置其大部分设置.有没有人确切地知道它做了什么但不做什么呢?

例如,我从这篇文章中看到它没有重置事务隔离级别

sql sql-server connection-pooling

42
推荐指数
1
解决办法
3万
查看次数

我可以阻止调用sp_reset_connection来提高性能吗?

我的探查器跟踪显示exec sp_reset_connection在每个sql批处理或过程调用之间调用.这是有原因的,但是如果我确信没有必要提高性能,我可以阻止它被调用吗?

更新:我认为这可以提高性能的原因有两个:

  1. SQL Server不需要重置连接状态.我认为这将是一个相对微不足道的改进.
  2. 减少网络延迟,因为客户端不需要发送exec sp_reset_connection,等待响应,然后发送它真正想要执行的任何sql.

第二个好处是我感兴趣的那个,因为在我的架构中,客户端有时与数据库有一定距离.如果每个sql批处理或rpc都需要双向往返,则会使任何网络延迟的影响加倍.消除这种双重调用可能会提高性能.

是的,我可以做很多其他事情来改善性能,比如重新构建应用程序,我是解决问题根本原因的忠实粉丝,但在这种情况下我只想知道是否可以阻止sp_reset_connection被称为.然后我可以测试是否有任何性能改进,并正确评估不调用它的风险.

这提示了另一个问题:与sp_reset_connection的网络通信是否真的如上所述?即客户端是否发送exec sp_reset_connection,等待响应,然后发送真正的SQL?或者这一切都在一块?

sql-server performance sp-reset-connection

13
推荐指数
1
解决办法
1万
查看次数

SqlConnection vs Sql Session.他们的生命一致吗?

我想为我的c#应用程序中的某些进程应用一些sql-session级别设置.

例如,我想DEADLOCK_PRIORITY为一些后台进程设置LOW.

问题是:

  1. 如果我打开一个新的SQL连接,那会启动一个新的sql-session吗?

  2. sql-session会一直存在,直到连接关闭?如果我在SqlConnection打开后立即应用我的设置,它们是否对在相同的情况下执行的所有查询有效SqlConnection

  3. 连接池怎么样?这可能是我的SET DEADLOCK_PRIORITY LOW设置将被我的系统中的其他进程(我不想要)重用,因为SqlConnection实际上并没有关闭(asp.net连接池决定重用它).

谢谢!

c# sql sql-server asp.net connection-pooling

12
推荐指数
1
解决办法
2003
查看次数

连接池并在返回时释放临时表

我正在使用带有连接池的 MySQL 临时表.

通常,在会话中创建的临时表会保留在该会话中,并在关闭连接时被删除.但是,由于我正在使用连接池,并且在java.sql.Connection.close()调用时实际上并未关闭物理连接,因此我发现临时表停留并影响下一个会话.

这会导致DB上的资源泄漏,因为临时表不会立即释放,以及由于表名冲突而导致的名称冲突.

直观地说,当我借用连接时,我期待一个干净的名单.如何实现这一目标?

  • 似乎没有与MySQL 相同的SQL Serversp_reset_connection.
  • 即使有,我也看不到dbcp2如何配置为在返回连接时调用它.
  • 返回池时始终关闭物理连接可以正常工作,但我无法看到dbcp2如何配置来执行此操作.

除临时表外,此问题还会影响:

mysql apache-commons-dbcp

5
推荐指数
1
解决办法
772
查看次数

使用会话拥有的SQL Server sp_getapplock和EF6 DbContexts是否安全?

我想知道使用EF上下文sp_getapplock和会话所有者类型的风险/安全性.基于文档,我的理解是会话所有者意味着如果在此之前没有明确释放,则会话结束时将释放锁定.我假设这也意味着连接结束.

我已经将这一切都用于事务拥有的锁,但这带来了其他问题和复杂性,所以我想知道如何使用会话拥有的锁以及它将如何或不会与行为DbContext及其连接发生冲突处理.

我不是100%确定DbContext默认情况下是如何工作的,无论是使用池还是每个上下文实例都打开并关闭它自己的连接(我读过的文档似乎暗示后者).对于这个问题,假设我没有做任何关于连接管理的事情(我很少这样做),所以EF正在处理它,或处理它的任何处理.

如果我创建一个DbContext实例,抓取连接,执行SQL来创建一个会话拥有的锁,正常使用上下文,释放锁并处理上下文,这会正常工作吗?(实际上,这将是一个IDisposable包装,以防止这种情况,但问题仍然存在.)

为了说明不好:

using (var ctx = new MyContext()) {
    var conn = ctx.Database.Connection.Open();
    conn.ExecuteSqlSomehow("sp_getapplock blahblah");
    try {
        // Lots of queries, savechanges, etc.
    } finally {
        // Oops I forgot to conn.ExecuteSql("sp_release the lock");
    }
}

await WatchMovieAsync();

using (var ctx = new MyContext()) {
    // Can this reuse the same connection, session and/or lock?
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 在处理实例后,另一个上下文可以以某种方式重用我的连接及其会话锁吗?
  2. 就此而言,另一个上下文(例如在另一个线程中)是否可以使用我发出锁定的连接,而原始线程仍然在using块内? …

c# sql-server entity-framework

5
推荐指数
1
解决办法
657
查看次数

如何向应用程序角色授予 db_owner 权限?

如何将db_owner固定数据库角色的所有权限和特权授予应用程序角色?

精简版

命令:

GRANT CONTROL ON [DatabaseName] TO [ApplicationRoleName];
Run Code Online (Sandbox Code Playgroud)

将是我想要的,但它失败了:

消息 15151,级别 16,状态 1,第 23 行
找不到对象“DatabaseName”,因为它不存在或您没有权限。

研究工作

我正在研究使用 SQL Server Application Roles

  • 它就像一个用户(因为它有一个用户名和密码)
  • 这就像一个角色

连接到服务器后,您的应用程序将运行一个存储过程以作为应用程序“登录”自己:

EXECUTE sp_SetAppRole @rolename = 'Contoso.exe', @password =
'Tm8gaSBkaWRuJ3QganVzdCBiYXNlNjQgZW5jb2RlIGEgcGFzc3dvcmQuIEl0J3Mgb25seSBhbiBleGFtcGxlIQ==';
Run Code Online (Sandbox Code Playgroud)

db_owner 的权限

通常,应用程序以作为db_owner固定角色成员的用户身份登录。该角色具有以下权限:db_owner

  • 对一切
  • 每张桌子上
  • 每一个观点
  • 每个存储过程、函数
  • 对于所有现有对象
  • 以及未来将存在的所有对象

而同时:

  • 您可以将用户置于数据库角色中
  • 您可以将用户置于应用程序角色中

您不能将应用程序角色置于数据库角色中

那么,问题来了:如何授予我的应用程序角色所有权限(即执行所有操作)?

角色权限

因此,现在是向角色授予权限的时候了。按照此页面的建议

GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO [Contoso.exe]; …
Run Code Online (Sandbox Code Playgroud)

sql-server security permissions sql-server-2005 application-role

5
推荐指数
1
解决办法
5386
查看次数

禁用sp_reset_connection

由于我遇到的一些问题,我正在尝试使用.NET Framework 4中的连接池.使用SQL事件探查器,我可以看到每次从连接池中获取连接时,都会执行存储过程sp_reset_connection.

要摆脱这种重置(我实际上不需要sp_reset_connection).我已经尝试将连接字符串中的连接重置参数设置为false,但这似乎没有任何效果.我在想,也许我误解了Connection reset参数的用途.

我注意到http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx中没有记录Connection reset参数.但它在许多其他地方也有提及,例如http://www.techrepublic.com/article/educate-yourself-about-net-sql-server-connection-string-syntax/6084879.

如果我将Conection Reset标志设置为无效值(例如'hello'),则在打开连接时会出现异常,表明实际使用了连接重置标志.

ADO.NET是否真的关心连接重置标志?

我的代码如下:

  static void Main(string[] args)
  {
     const string connectionString =
        "Data Source=(local);Initial Catalog=MyDatabse;User ID=sa;Password=<removed>;Connection Timeout=5;Pooling=true;Min Pool Size=1; Max Pool Size=1; Enlist=false; Connection Reset=false;";

     var connections = new List<SqlConnection>();
     for (int i = 0; i < 1000000; i++)
     {
        using (var conn = new SqlConnection(connectionString))
        {
           conn.Open();

           SqlCommand command = new SqlCommand("SELECT * FROM DatabaseVersion", conn);
           command.ExecuteNonQuery();

           connections.Add(conn);
        }
     }
  }
Run Code Online (Sandbox Code Playgroud)

.net sql-server ado.net connection-pooling

4
推荐指数
1
解决办法
2485
查看次数

使用块存储过程

我正在尝试习惯使用C#中的"使用"块,但我很难理解何时应该使用它们.

这是一个例子.

我的原始代码,没有using块:

SqlConnection conn = new SqlConnection(cCon.getConn());
    SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    try
    {
        conn.Open();
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    { }
    finally
    {
        conn.Close();
    }
Run Code Online (Sandbox Code Playgroud)

但我真的应该这样做吗?或者我应该使用(SqlConnection conn = new SqlConnection(cCon.getConn()))?请帮我理解这个.我最初这样做的方式错了吗?

SqlConnection conn = new SqlConnection(cCon.getConn());
   using( SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    try
    {
        conn.Open();
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    { }
    finally
    { …
Run Code Online (Sandbox Code Playgroud)

.net c# asp.net stored-procedures

2
推荐指数
1
解决办法
2316
查看次数