SQL服务器-单用户模式-坚持哪个用户
SQL Server - Single User Mode - Persist Which User
问题
有没有办法在将数据库置于单用户模式时指定该用户(在我的例子中是当前用户),并确保即使在该用户断开连接后,单个会话仍保留给那个定义的用户;也就是说,它是真正的单用户而不是单并发用户?
背景
给出一些背景...
我们有一些脚本可以在我们的测试环境中刷新数据。
最近一个失败,错误指出脚本 运行 所在的用户帐户没有访问数据库的权限。
经调查,该用户是数据库的系统管理员;所以这显然不是真的。
但是,我发现该脚本将数据库置于 Single User
模式。
当查看数据库上的活动会话时,我可以看到单个用户与预期帐户不同(而是属于间歇性轮询该数据库的系统的另一个服务帐户)。
我的假设是发生了以下情况:
- 脚本 运行s 作为 UserA
- 脚本将数据库置于单用户模式
- 脚本执行一些 query/ies
- 脚本在执行一些其他任务时关闭当前连接
- UserB 尝试连接到数据库;成功,因为 UserA 会话现已关闭
- UserB 的会话保持打开状态(因为 UserB 是具有连接池的服务,即使在操作完成后会话仍然保持打开状态)。
- UserA 尝试重新连接到 DB;访问被拒绝,因为 UserB
占用了单个会话
有多种可能的解决方案。
- 重写脚本以保持持久连接(可能需要付出很多努力,尤其是因为我不熟悉代码)
- 禁用所有可能尝试间歇性连接的服务(有点违背了使用单用户模式的意义/也需要付出很多额外的努力来调查所有可能连接的帐户并维护它)
- 在脚本中添加捕获以杀死竞争的 SPID,从而回收单个用户会话(我不喜欢杀死 SPID,因为这会影响事务完整性)
- 使用魔法(即看到这个问题的公认答案;希望如此)
更新
该代码使用 PowerShell 的 Invoke-SqlCmd
,它为每个命令创建和删除连接 运行;因此,一旦将数据库置于单用户模式,连接就会断开。
我查看了这个命令参数,看看是否有 pooling/persisting 连接的选项,但我能找到的最接近的是 DedicatedAdministratorConnection
,尽管如此,我似乎应该避开 (http://www.brentozar.com/archive/2011/08/dedicated-admin-connection-why-want-when-need-how-tell-whos-using/)我最初的希望。
抱歉,没有魔法。没有适合您需要的本地解决方案。 SQL服务器确保设置单用户模式的会话是存活的会话。一旦该会话终止(用户断开连接、网络中断等...),"slot" 现在可用于任何其他连接,包括某些后台工作线程或 SSMS 对象浏览器。 DAC 对于救援行动以外的任何事情都不是一个好主意。
您可以使用 sqlcmd 运行 脚本或从 PS 调用脚本文件(invoke-sqlcmd -inputfile "c:\mysqlfile.sql" -serverinstance "servername\serverinstance" -database "mydatabase") 所以它是在单个会话中执行的,而不是 PS 中的单个会话。
还有许多其他方法可以防止用户连接到数据库(触发器、安全性等...),但这些方法通常存在风险,因为您需要非常小心地实施这些块并确保这些块是正确的完成后安全正确地移除。这很重要,因为您需要考虑连接丢失或实例丢失以及如何处理恢复或恢复后的状态。变得非常混乱,非常快,所以小心行事。
问题
有没有办法在将数据库置于单用户模式时指定该用户(在我的例子中是当前用户),并确保即使在该用户断开连接后,单个会话仍保留给那个定义的用户;也就是说,它是真正的单用户而不是单并发用户?
背景
给出一些背景...
我们有一些脚本可以在我们的测试环境中刷新数据。
最近一个失败,错误指出脚本 运行 所在的用户帐户没有访问数据库的权限。
经调查,该用户是数据库的系统管理员;所以这显然不是真的。
但是,我发现该脚本将数据库置于 Single User
模式。
当查看数据库上的活动会话时,我可以看到单个用户与预期帐户不同(而是属于间歇性轮询该数据库的系统的另一个服务帐户)。
我的假设是发生了以下情况:
- 脚本 运行s 作为 UserA
- 脚本将数据库置于单用户模式
- 脚本执行一些 query/ies
- 脚本在执行一些其他任务时关闭当前连接
- UserB 尝试连接到数据库;成功,因为 UserA 会话现已关闭
- UserB 的会话保持打开状态(因为 UserB 是具有连接池的服务,即使在操作完成后会话仍然保持打开状态)。
- UserA 尝试重新连接到 DB;访问被拒绝,因为 UserB 占用了单个会话
有多种可能的解决方案。
- 重写脚本以保持持久连接(可能需要付出很多努力,尤其是因为我不熟悉代码)
- 禁用所有可能尝试间歇性连接的服务(有点违背了使用单用户模式的意义/也需要付出很多额外的努力来调查所有可能连接的帐户并维护它)
- 在脚本中添加捕获以杀死竞争的 SPID,从而回收单个用户会话(我不喜欢杀死 SPID,因为这会影响事务完整性)
- 使用魔法(即看到这个问题的公认答案;希望如此)
更新
该代码使用 PowerShell 的 Invoke-SqlCmd
,它为每个命令创建和删除连接 运行;因此,一旦将数据库置于单用户模式,连接就会断开。
我查看了这个命令参数,看看是否有 pooling/persisting 连接的选项,但我能找到的最接近的是 DedicatedAdministratorConnection
,尽管如此,我似乎应该避开 (http://www.brentozar.com/archive/2011/08/dedicated-admin-connection-why-want-when-need-how-tell-whos-using/)我最初的希望。
抱歉,没有魔法。没有适合您需要的本地解决方案。 SQL服务器确保设置单用户模式的会话是存活的会话。一旦该会话终止(用户断开连接、网络中断等...),"slot" 现在可用于任何其他连接,包括某些后台工作线程或 SSMS 对象浏览器。 DAC 对于救援行动以外的任何事情都不是一个好主意。
您可以使用 sqlcmd 运行 脚本或从 PS 调用脚本文件(invoke-sqlcmd -inputfile "c:\mysqlfile.sql" -serverinstance "servername\serverinstance" -database "mydatabase") 所以它是在单个会话中执行的,而不是 PS 中的单个会话。
还有许多其他方法可以防止用户连接到数据库(触发器、安全性等...),但这些方法通常存在风险,因为您需要非常小心地实施这些块并确保这些块是正确的完成后安全正确地移除。这很重要,因为您需要考虑连接丢失或实例丢失以及如何处理恢复或恢复后的状态。变得非常混乱,非常快,所以小心行事。