ret*_*tif 8 sql-server availability-groups distributed-transactions
我们有一个由 2 个服务器组成的 Always On“集群”(还会有更多),所以一个是PRIMARY,其他是SECONDARY。这个想法是将 SECONDARY 用作只读副本,因此它在某种程度上是一个搜索服务器。
我知道如何在 C# 中设置 ConnectionString 所以它将使用 SECONDARY 副本 - 只需添加ApplicationIntent=ReadOnly
.
但是如果我使用分布式查询,我不明白如何从存储过程中解决 SECONDARY。有没有办法为查询设置一些参数(如 WITH 语句或其他东西),因此查询将仅使用副本而不使用 PRIMARY 节点?
问题是,很明显,从一开始server1是 PRIMARY,server2是 SECONDARY,但是当server1 出现故障时,server2是 PRIMARY,server1在修复后将是 SECONDARY。所以我不能只使用静态server2的名称。
到目前为止,我已经设法将当前副本的服务器名称作为变量并在 EXEC 中使用它:
-- find first available replica
DECLARE @replicaServer nvarchar(50)
SELECT TOP 1
@replicaServer = RCS.replica_server_name
FROM
sys.availability_groups_cluster AS AGC
INNER JOIN sys.dm_hadr_availability_replica_cluster_states AS RCS
ON RCS.group_id = AGC.group_id
INNER JOIN sys.dm_hadr_availability_replica_states AS ARS
ON ARS.replica_id = RCS.replica_id
INNER JOIN sys.availability_group_listeners AS AGL
ON AGL.group_id = ARS.group_id
WHERE ARS.role_desc = 'SECONDARY'
AND connected_state = 1
-- and query it
DECLARE @cmd nvarchar(MAX) = 'SELECT * FROM [' + @replicaServer + '].[somebase].[someschema].[sometable]'
EXEC (@cmd)
Run Code Online (Sandbox Code Playgroud)
但我想这是一种耻辱。
经过一些帮助和提示(特别是感谢Andriy M),我已经设法了解我真正想要什么以及如何去做。微软的这篇文章也有帮助:https : //technet.microsoft.com/en-us/library/hh403414.aspx
首先,我必须创建一个只读侦听器。然后在另一台服务器上添加这样的链接服务器(借自:https : //stackoverflow.com/a/19585304):
使用 [大师] 走 EXEC master.dbo.sp_addlinkedserver @server = N'cluster-readonly', -- 只是一个名字 @srvproduct = N'SQL', -- 除了 'SQL Server' @provider = N'SQLNCLI11', @datasrc = N'ClusterListener', -- 只读监听器的名称 @provstr = N'ApplicationIntent=ReadOnly', @catalog = N'AnyActualDataBase' -- 像'master'这样的系统数据库不好 走
我如何检查,我在哪里:
SELECT * FROM OPENQUERY([集群只读], 'SELECT @@SERVERNAME')
这里有一些技巧 - 如果我不指定@catalog
,那么由于某些原因,连接将连接到 PRIMARY 节点。
SQL Server Management Studio 支持在通过“连接到服务器”对话框连接到服务器时向连接字符串添加项目:
添加ApplicationIntent=ReadOnly;
到“附加连接参数”框(如上图所示)应该可以完成您的需要。
Database='YourDatabase';
如果您的默认数据库不属于可用性组,您可能还需要添加。如果您不添加该Database='YourDatabase';
部分,您仍然可以连接到主要主机,因为默认主数据库不是您的可用性组的一部分。