AlwaysOn可用性组中的数据库恢复为普通数据库

时间:2018-06-10 21:33:46

标签: database-restore sql-server-2017 alwayson

从SQL Server 2017中AlwaysOn高可用性组中的数据库集恢复正常的SQL数据库时遇到问题。

我将生产数据库的副本还原到另一台服务器,用作QA测试数据库,并使用不同的名称 - MyDB_demo

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

即使我的conn str指向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异常,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,Boolean isInternal,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,String method,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数据集,DataTable [] datatables,Int32 startRecord,Int32 maxRecords,String srcTable,IDbCommand命令,CommandBehavior行为)+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连接,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

新恢复的数据库(名为now MyDB_demo)中是否存在存储生产数据库的原始名称以及为什么要尝试访问它的引用?

任何建议都表示赞赏。

修改

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

所以服务器有:

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

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

但我没有:连接字符串(我经过双重检查)试图连接到QA db,MyDB_demo。

以下是一些其他信息:

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

所以看起来某种方式连接字符串MIGHT被改变(!!!)是NET应用程序本身的某种方式,并且只针对这个存储过程?

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

谢谢

1 个答案:

答案 0 :(得分:0)

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

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

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

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

修改

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

另一个问题(开放):

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

赞赏任何评论