Skip to content

Commit 8dacfa2

Browse files
Get-DbaReplSubscription: Also check distribution DB for pull subscriptions missing from syssubscriptions (#10218)
1 parent dc58134 commit 8dacfa2

1 file changed

Lines changed: 98 additions & 1 deletion

File tree

public/Get-DbaReplSubscription.ps1

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ function Get-DbaReplSubscription {
66
.DESCRIPTION
77
Retrieves detailed information about replication subscriptions, showing which subscriber instances are receiving data from publications. This is essential for monitoring replication topology, troubleshooting subscription issues, and auditing data distribution across your SQL Server environment. You can filter results by database, publication name, subscriber instance, subscription database, or subscription type (Push/Pull) to focus on specific replication relationships.
88
9+
Pull subscriptions that exist only in the distribution database (but not in the publisher's syssubscriptions) are also returned, to handle cases where subscriptions were set up outside the normal creation process.
10+
911
.PARAMETER SqlInstance
1012
The target SQL Server instance or instances.
1113
@@ -149,6 +151,9 @@ function Get-DbaReplSubscription {
149151
Stop-Function -Message "Error occurred while getting publications from $instance" -ErrorRecord $_ -Target $instance -Continue
150152
}
151153

154+
# Track subscriptions already emitted to avoid duplicates from the distribution DB check
155+
$foundSubscriptionKeys = @{}
156+
152157
try {
153158
foreach ($subs in $publications.Subscriptions) {
154159
Write-Message -Level Verbose -Message ('Get subscriptions for {0}' -f $sub.PublicationName)
@@ -166,6 +171,9 @@ function Get-DbaReplSubscription {
166171
}
167172

168173
foreach ($sub in $subs) {
174+
$subKey = "$($sub.SubscriberName)|$($sub.SubscriptionDBName)|$($sub.PublicationName)|$($sub.DatabaseName)"
175+
$foundSubscriptionKeys[$subKey] = $true
176+
169177
Add-Member -Force -InputObject $sub -MemberType NoteProperty -Name ComputerName -Value $server.ComputerName
170178
Add-Member -Force -InputObject $sub -MemberType NoteProperty -Name InstanceName -Value $server.ServiceName
171179
Add-Member -Force -InputObject $sub -MemberType NoteProperty -Name SqlInstance -Value $server.DomainInstanceName
@@ -176,6 +184,95 @@ function Get-DbaReplSubscription {
176184
} catch {
177185
Stop-Function -Message "Error occurred while getting subscriptions from $instance" -ErrorRecord $_ -Target $instance -Continue
178186
}
187+
188+
# Also check distribution database for pull subscriptions that may be missing from publisher's syssubscriptions.
189+
# This handles cases where pull subscriptions were created outside the normal process and only exist in distribution.dbo.MSsubscriptions.
190+
if (-not $Type -or "Pull" -in $Type) {
191+
try {
192+
$replServer = New-Object Microsoft.SqlServer.Replication.ReplicationServer
193+
$replServer.ConnectionContext = $server.ConnectionContext
194+
195+
if ($replServer.IsPublisher -and $replServer.DistributorInstalled -and $replServer.DistributorAvailable) {
196+
$distributorName = $replServer.DistributionServer
197+
$distributionDbName = $replServer.DistributionDatabase
198+
199+
try {
200+
# Reuse the existing connection if the distributor is the same server
201+
if ($distributorName -eq $server.ComputerName -or $distributorName -eq $server.DomainInstanceName) {
202+
$distributorServer = $server
203+
} else {
204+
$distributorServer = Connect-DbaInstance -SqlInstance $distributorName -SqlCredential $SqlCredential
205+
}
206+
207+
$distQuery = "
208+
SELECT DISTINCT
209+
a.subscriber_name AS SubscriberName,
210+
a.subscriber_db AS SubscriptionDBName,
211+
p.publisher_db AS DatabaseName,
212+
p.publication AS PublicationName
213+
FROM MSdistribution_agents a
214+
INNER JOIN MSsubscriptions s ON s.agent_id = a.id AND s.subscription_type = 1
215+
INNER JOIN MSpublications p ON p.publication_id = s.publication_id
216+
"
217+
218+
$splatDistQuery = @{
219+
SqlInstance = $distributorServer
220+
Database = $distributionDbName
221+
Query = $distQuery
222+
}
223+
$distPullSubs = Invoke-DbaQuery @splatDistQuery
224+
225+
# Build a lookup of the publications we queried so we only include relevant subscriptions
226+
$publicationKeys = @{}
227+
foreach ($pub in $publications) {
228+
$pubKey = "$($pub.DatabaseName)|$($pub.Name)"
229+
$publicationKeys[$pubKey] = $true
230+
}
231+
232+
# Convert SubscriberName filter to strings for comparison
233+
$subscriberNameStrings = @()
234+
if ($SubscriberName) {
235+
$subscriberNameStrings = $SubscriberName | ForEach-Object { $_.ToString() }
236+
}
237+
238+
foreach ($distSub in $distPullSubs) {
239+
# Only process subscriptions for publications we already queried
240+
$pubKey = "$($distSub.DatabaseName)|$($distSub.PublicationName)"
241+
if (-not $publicationKeys.ContainsKey($pubKey)) { continue }
242+
243+
# Apply subscriber name filter
244+
if ($subscriberNameStrings -and $distSub.SubscriberName -notin $subscriberNameStrings) { continue }
245+
246+
# Apply subscription database filter
247+
if ($SubscriptionDatabase -and $distSub.SubscriptionDBName -notin $SubscriptionDatabase) { continue }
248+
249+
# Skip subscriptions already returned via SMO
250+
$subKey = "$($distSub.SubscriberName)|$($distSub.SubscriptionDBName)|$($distSub.PublicationName)|$($distSub.DatabaseName)"
251+
if ($foundSubscriptionKeys.ContainsKey($subKey)) { continue }
252+
253+
# Emit subscriptions found only in the distribution database
254+
$subObj = [PSCustomObject]@{
255+
ComputerName = $server.ComputerName
256+
InstanceName = $server.ServiceName
257+
SqlInstance = $server.DomainInstanceName
258+
DatabaseName = $distSub.DatabaseName
259+
PublicationName = $distSub.PublicationName
260+
Name = "$($distSub.PublicationName)-$($distSub.SubscriberName)-$($distSub.SubscriptionDBName)"
261+
SubscriberName = $distSub.SubscriberName
262+
SubscriptionDBName = $distSub.SubscriptionDBName
263+
SubscriptionType = "Pull"
264+
}
265+
266+
Select-DefaultView -InputObject $subObj -Property ComputerName, InstanceName, SqlInstance, DatabaseName, PublicationName, Name, SubscriberName, SubscriptionDBName, SubscriptionType
267+
}
268+
} catch {
269+
Write-Message -Level Warning -Message "Could not query distribution database on $distributorName for additional pull subscriptions from $instance"
270+
}
271+
}
272+
} catch {
273+
Write-Message -Level Verbose -Message "Unable to check distribution database for additional pull subscriptions from $instance"
274+
}
275+
}
179276
}
180277
}
181-
}
278+
}

0 commit comments

Comments
 (0)