AlwaysOn 可用性组中的数据库还原为普通数据库



我在使用 SQL Server 2017 中从 AlwaysOn 高可用性组中的数据库集还原的普通 SQL 数据库时遇到问题。

我将生产数据库的副本还原到其他服务器,用作 QA 测试数据库,名称也不同 - MyDB_demo

问题是,QA 应用程序副本(与具有新开发增强功能的生产相同代码)在某些时候出现错误。

即使我的连接指向MyDB_demo,我也会收到以下错误

[SqlException (0x80131904):目标数据库 ('MyDB') 位于可用性组中,当应用程序意向设置为只读时,当前可供连接访问。有关应用程序意向的详细信息,请参阅 SQL Server 联机丛书。

System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) +2444190 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean
breakConnection, Action 1 wrapCloseInAction) +5775712
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +285
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +4169
System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() +58
System.Data.SqlClient.SqlDataReader.get_MetaData() +89
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, BooleanisInternal, Boolean forDescribeParameterEncryption) +409 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async,
Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) +2127
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Stringmethod, TaskCompletionSource'1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) +911 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +64 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior

, String method) +240
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +41
System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) +12 System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) +
139
System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) +136
System.Data.Common.DbDataAdapter.Fill(DataSet dataSet) +88 MyApp.SqlHelper.ExecuteDataset(SqlConnection
connection, CommandType commandType, String commandText, SqlParameter[] commandParameters) +163
MyApp.PermitFunctions.GetSystemMessages(String sp, Int32 iPermitID, Int32 iAppID, SqlConnection cn) +219
MyApp.Municipality.LoadSystemMessage() +3869 MyApp.Municipality.Page_Load(Object sender, EventArgs e) +
101
System.Web.UI.Control.OnLoad(EventArgs e) +95
System.Web.UI.Control.LoadRecursive() +59
System.Web.UI.Control.LoadRecursive() +131
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +678

新还原的数据库(现在命名为MyDB_demo)中是否有任何引用存储生产数据库的原始名称,为什么它试图访问它?

任何建议不胜感激。

编辑

实际上,用于还原MyDB_demo的服务器是 AlwasyOn 可用性组的辅助节点之一;它还包含生产数据库的 RO 副本MyDB

所以服务器有:

  • 生产数据库的RO副本(MyDB)
  • 为 QA 恢复的正常独立数据库 -MyDB_demo

因此,我理解错误消息 - 如果我尝试从连接字符串直接访问生产数据库的辅助 RO 副本,这将是有意义的。

但我没有:连接字符串(我仔细检查)正在尝试连接到 QA db,MyDB_demo。

以下是一些其他信息:

  • 错误在ExecuteDataset函数中的SQLHelper类(MS 中用于与 SQL Server 配合使用的帮助程序类)中引发
  • 该错误仅在一个存储过程中引发 - 许多其他存储过程和直接SQL语句运行良好
  • 我检查了存储过程,认为它可能意外地包含对数据库名称的硬编码引用 - 它没有
  • 和奇怪的部分 - 我使用与 SSMS 中的应用程序调用的相同参数运行存储过程 - 它运行良好 - 没有错误

所以看起来连接字符串可能会以某种方式被 NET 应用程序本身更改 (!!),并且仅适用于此存储过程?

有人遇到过这样的事情吗?

谢谢

由于奇怪的(阅读:愚蠢)情况,罪魁祸首 SP 仅在从应用程序内调用时才失败,但在 SSMS 中尝试时运行正常,我尝试了一种"愚蠢"的方法:我检查了它的代码,注释掉了两个设置了子选择的字段,如select top 1 from ..... where....(实际上我用虚拟值替换了 theit 值),我更改了一个最初指定的Order By字段,如"InspectionType" Desc, 我从中删除了引号。

这样做时,即使从应用程序调用,SP 也会突然开始正常工作。 然后我将所有更改恢复为原始更改(添加回引号并放回子选择),SP继续正常工作。

所以。。。问题解决了。 愚蠢问题的愚蠢方法(?!?!)

无论如何,如果有人对可能发生的事情有更好的想法或解释,我会很高兴听到它


编辑

我想我明白解决方法。 通过编辑和保存存储过程,重新编译了其查询计划。 因此,原始错误可能是由旧查询计划引起的。 但是为什么它引用了数据库名称?查询计划中是否引用了实际数据库名称?这对我来说看起来有点奇怪。

还有一个问题(开放):

SQL Server 优化器是否检测数据库是否在高可用性模式下运行,在优化查询时,它是否确定查询是否为只读模式并自动将其重定向到只读节点?即使连接字符串中不存在应用程序意图只读参数? 因为在这种情况下不是这样,即使在生产中也是如此 - 我们刚刚实现了 AlwaysOn 功能,并且正在更新应用程序以利用 R/O 节点。

任何意见都值得赞赏

最新更新