Sql server ADO.NET SQLServer:如何防止关闭的连接持有S-DB锁?
我创建了一个SqlConnection对象,当然了。我需要一个关闭的连接来不锁定数据库对象。如何防止关闭的连接锁定Sql server ADO.NET SQLServer:如何防止关闭的连接持有S-DB锁?,sql-server,ado.net,tcp,connection-pooling,Sql Server,Ado.net,Tcp,Connection Pooling,我创建了一个SqlConnection对象,当然了。我需要一个关闭的连接来不锁定数据库对象。如何防止关闭的连接锁定 为不知道的人解释上述句子: 关闭ADO或ADO.NET连接时,实际上并不是切断与SQL Server的连接。ADO/ADO.NET基础结构保持连接,以防您再次使用它。这些连接一直在所谓的“连接池”中徘徊 几分钟不使用后,连接将实际关闭。虽然,不是真的。TCP/IP有它自己的方法来保持TCP连接打开几分钟(处于“关闭\u等待”状态)。如果您要求再次打开到同一IP:端口的TCP连接
为不知道的人解释上述句子:
- 关闭ADO或ADO.NET连接时,实际上并不是切断与SQL Server的连接。ADO/ADO.NET基础结构保持连接,以防您再次使用它。这些连接一直在所谓的“连接池”中徘徊
- 几分钟不使用后,连接将实际关闭。虽然,不是真的。TCP/IP有它自己的方法来保持TCP连接打开几分钟(处于“关闭\u等待”状态)。如果您要求再次打开到同一IP:端口的TCP连接,则可以执行此操作。如果是这样,它可以使用已经打开的TCP连接
- 使用连接池和SQL Server,仍然可以建立到SQL Server的连接。每个连接都有其所在的数据库上下文。只要连接位于该数据库中:它就持有该数据库上的共享数据库(S-DB)锁
- 共享数据库锁的简单意思是,“请不要在我在数据库中时删除此数据库。”
我现在的特别解决方案是每次开发人员调用Dispose时:
connection.Dispose()
将其更改为对全局辅助函数的调用:
Database.DisposeConnection(connection);
这会将数据库上下文更改为主:
public static void DisposeConnection(SqlConnection connection)
{
//Stop holding a database lock - in my database at least
ADOHelper.ExecuteNonQuery(connection, "USE master");
connection.Dispose();
}
它解决了我眼前的问题;关闭的连接没有锁定我的数据库
但现在我担心连接池会让大脑混乱——因为我在背后切换了数据库上下文
如果有人不知道或不这么想: 发件人: 关闭和处置在功能上 相当于
阅读注释时,您希望还原它 好的,把它离线 恢复不是应用程序应该做的事情,所以DBA在恢复之前运行它
ALTER DATABASE foo SET OFFLINE WITH ROLLBACK IMMEDIATE
你试过了吗
从MSDN:
ClearPool清除连接池
这与
连接。如果需要其他连接
与正在使用的连接关联
在打电话时,他们是
适当标记并丢弃
(而不是返回到
当对其调用Close时
只需在每个连接上调用ClearPool,但如果这样做,您将失去池的好处
public class DataFactory
{
public SqlConnection CreateConnection(string connString)
{
SqlConnection conn = new SqlConnection(connString);
SqlClient.ClearPool(conn);
return conn;
}
}
或者,您可以使用连接字符串的pooling属性禁用所有池:
string connString = "Data Source=MYSERVER;Initial Catalog=myDb;Integrated Security=true;Pooling=false"
正如您所说,当您关闭或处置一个连接时,它会返回到池中,但实际上并没有关闭 然后需要在中执行什么操作来关闭池中的所有连接。这可以通过ClearAllPools命令完成 ClearAllPools重置(或清空)连接池。如果有 发生故障时正在使用的连接 调用时,它们会被适当地标记 并将被丢弃(而不是 在关闭时返回到池中) 他们被召唤 还有一个ClearPool命令,它只对单个连接执行相同的操作 希望这有帮助
Shiraz您可以将数据库置于单用户模式以恢复它。IIRC,像这样的
ALTER DATABASE TheDatabaseToRestore SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE TheDatabaseToRestore
FROM DISK =N'Z:\Path\To\Backup\BackupFile';
ALTER DATABASE TheDatabaseToRestore SET MULTI_USER;
请参阅:和/或了解更多背景信息
编辑:单用户模式用于备份和恢复(在非快速版上,我经常使用它)。使用它将取消所有其他连接,并且无法创建新连接。我没有使用过各种“with”选项,例如“rollbackimmediate”,但它们的用法似乎很简单。首先执行“USE TempDB;”。然后关上它
或者“使用master;”,如果你更喜欢的话
在正常的生产操作期间,这些数据库上的S-DB锁都不重要,因为您无法摆脱其中任何一个并继续运行服务器。另外,请尝试使用“using”关键字,而不是手动调用Dispose()。只是好奇,为什么这是个问题?这是个问题,因为你不能对数据库中的用户进行恢复。@Ray Booysen:我不能这样做,因为我必须在关闭连接之前更改数据库上下文。在SQL Server中执行恢复之前,您可以将连接/用户踢出数据库……如果DBA是63岁的祖母,她想要回她的刺绣设计呢?除非你提出在她的孙子修好她的电脑后开车去她家取回她的设计。DBA是否使用应用程序来运行恢复?也许是企业经理?SSMS?如果数据库上有其他连接(如维护作业),osql?connection.close将不起作用。但我怀疑根据你的评论你有这些。坚持使用.netWon。除非是我写的,否则我不会在快速版上做任何维护工作。我没有。是的,我真的不想失去100%的时间连接池的好处,因为恢复可能会发生0.0001%的时间。那么,在恢复数据库时,最好的办法就是像其他人所说的那样,将其置于单用户模式。您完全停止了进程,因此所有连接都肯定已关闭。我还没有进行测试,但这是否会导致SQL Server关闭池中所有已关闭的连接?如果是这样的话,这将是一个非常好的解决方案。不过,我认为您需要使用单独的SQL登录来实现此连接,以便进行管理。否则,您的所有连接仍然满足单用户标准,并且不会关闭。单用户模式更准确地说是单连接