SQL Server - 单用户模式 ​​- 持续使用哪个用户

时间:2015-10-29 16:51:48

标签: sql-server tsql sql-server-2008-r2 single-user invoke-sqlcmd

问题

在将数据库置于单用户模式时,有没有办法指定该用户(在我的情况下是当前用户),并确保即使在该用户断开连接后,单个会话也保留为该定义的用户;即所以它是真正的单用户而不是单并发用户?

背景

提供一些背景......

我们有一些脚本可以在我们的测试环境中刷新数据。 最近有一个错误,出现错误,指出运行脚本的用户帐户无法访问数据库。 经过调查,用户是数据库中的系统管理员;所以这显然不是真的。 但是,我发现该脚本将数据库置于Single User模式。 查看数据库上的活动会话时,我可以看到单个用户与预期帐户不同(而不是属于系统间歇性轮询此数据库的另一个服务帐户)。 我的假设是发生了以下情况:

  • 脚本以UserA
  • 运行
  • 脚本将DB置于单用户模式
  • 脚本执行一些查询/ ies
  • 脚本在执行其他任务时关闭当前连接
  • UserB尝试连接到DB; UserA会话现已关闭
  • 成功
  • UserB的会话保持打开状态(因为UserB是一个带连接池的服务,即使在操作完成后会话保持打开状态)。
  • UserA尝试重新连接到DB; UserB
  • 执行单个会话时拒绝访问

有各种可能的解决方案。

  • 重写脚本以保持持久连接(可能需要付出很多努力,尤其是因为我不熟悉代码)
  • 禁用所有可能尝试间歇性连接的服务(有点破坏了使用单用户模式的点/还有很多额外的工作来调查可能连接的所有帐户,并保持这一点)
  • 在脚本中添加一个捕获来杀死竞争的SPID,从而回收单个用户会话(我不喜欢杀死SPID,因为这会影响事务完整性)
  • 使用魔法(即看到这个问题的接受答案;希望如此)

更新

代码使用PowerShell' Invoke-SqlCmd,它为每个命令运行创建和删除连接;因此,只要数据库处于单用户模式,连接就会被删除。 我查看了这个命令参数,看看是否有池化/持久连接的选项,但我能找到的最接近的是DedicatedAdministratorConnection,看起来我应该完全避开(http://www.brentozar.com/archive/2011/08/dedicated-admin-connection-why-want-when-need-how-tell-whos-using/)尽管我的初始希望。

1 个答案:

答案 0 :(得分:0)

抱歉,没有魔力。您无需本机解决方案。 SQL Server确保设置单用户模式的会话是幸存的会话。一旦该会话终止(用户断开连接,网络损坏等),“插槽”现在可用于任何其他连接,包括某些后台工作线程或SSMS对象浏览器。除救援行动外,DAC不是一个好主意。

您可以使用sqlcmd运行脚本或从PS调用脚本文件(invoke-sqlcmd -inputfile“c:\ mysqlfile.sql”-serverinstance“servername \ serverinstance”-database“mydatabase”),这样就可以在单个会话而不是来自PS的单个会话。

还有许多其他方法可以阻止用户连接到数据库(触发器,安全性等等),但这些方法通常存在风险,因为您需要非常小心地实现这些块并确保块是安全的完成后正确删除。这是非常重要的,因为您需要考虑丢失连接或丢失实例以及如何在恢复或恢复后处理状态。得到真正的凌乱,真正的快速,所以谨慎。