我有一个Powershell脚本,它使用invoke-sqlcmd
将脚本应用于一系列开发数据库。我遍历一个脚本列表并将其与数据库的当前版本级别进行比较,然后应用所需的脚本以使DB达到它所需的发布级别。某些数据库是参考数据库,处于READ_ONLY状态。我连接到那些数据库运行一个alter DB脚本,将它们设置为READ_WRITE应用脚本然后将其更改回READ_ONLY。整体而言,脚本运行良好,问题是当PowerShell首次打开与数据库的连接并应用第一个脚本然后将数据库更改回READ_ONLY数据库已锁定对象时。我已经将它追溯到之前的连接和一个Shared_Transaction_Workspace锁(sys.dm_tran_locks),看起来是以前的powershell连接。为什么在invoke-sqlcmd
完成后这个连接仍然打开,有什么我可以做的吗?我是否可以强制invoke-sqlcmd
为每次调用cmdlet使用新连接?
我尝试了一个混乱的修复程序来杀死有问题的连接,然后重试连接,但我认为有更好的东西。
我一直这样做,似乎有效:
[System.Data.SqlClient.SqlConnection]::ClearAllPools()
嗯,我知道这是一个非常古老的帖子,来自微软的人告诉我解决了这个问题(正如David Brabant所提到的那篇文章),但也许我不是最幸运的人,必须做一个解决方法才能让它发生。
即使运行Microsoft SQL Server 2012(SP1) - 11.0.3128.0(X64)我也有同样的问题,经过一些研究后我得到了一个从Invoke-Sqlcmd获取一些参数作为输出的方法,所以我可以得到当前的会话ID来自SQL Server的内置@@ SPID全局变量的用户进程,并与ADO.NET建立连接以执行KILL子句以关闭打开的连接。
#Invoke the Invoke-Sqlcmd to execute an script from a file
Invoke-Sqlcmd -Server "[SERVER_NAME]" -Database [DATABASE_NAME] -Username [USER] -Password [PASSWORD] -InputFile [DOT_SQL_FILE_PATH]
#Invoke the Invoke-Sqlcmd to execute a inline SQL statement to get the SessionID as a Powershell variable
$SQLSession = Invoke-Sqlcmd -Server "[SERVER_NAME]" -Database [DATABASE_NAME] -Username [USER] -Password [PASSWORD] -query "select @@spid as SessionID"
# Build query to execute KILL clause
$DbQuery = "KILL " + $SQLSession.SessionID;
# Create SQL connection with ADO.NET
$DbConnection = New-Object System.Data.SqlClient.SqlConnection
$DbConnectionString = "Server = [SERVER_NAME]; Database = [DATABASE_NAME]; User ID=[USER]; Password=[PASSWORD];"
$DbConnection.ConnectionString = $DbConnectionString
$DbConnection.Open()
# Create SQL command for KILL clause
$DbCommand = New-Object System.Data.SQLClient.SQLCommand
$DbCommand.Connection = $DbConnection
$DbCommand.CommandText = $DbQuery
# Execute KILL clause
$DbCommand.ExecuteNonQuery()
# Close connection
$DbConnection.Close()
我希望它有所帮助
即使我使用的是最新版本的SSMS(版本16.5.3 - Build 13.0.16106.4),我仍然会遇到这个问题。我还没弄清楚强制连接关闭的“正确”方式是什么,但我有一个简单的解决办法,并为我解决了问题。如果您只需要从数据库中获取连接,则可以执行以下操作:
Invoke-Sqlcmd -ServerInstance "SOME_SERVER" -Database "SOME_DB" ...
Invoke-Sqlcmd -ServerInstance "SOME_SERVER" -Database "SOME_DB" -Query "use [master];"
这会将连接切换到master,从而将其从感兴趣的数据库中删除。如果你绝对需要关闭连接,我认为你需要求助于SqlClient等。