You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while implementing [#1876], and deliberately left out of that PR.
[#1876] made the two blocking collectors' contentious_object labels agree at the incident identity, and in the same change [#1876] corrected the blocked_process_report sentinel to name the LOCK RESOURCE's database (DB_NAME(resource_database_id)) rather than the event's, because for a cross-database lock those differ and the event's names where the blocked session was merely running.
The DMV side's synthesized sentinel does not have that information available where it is built.
Why
The normalizer runs in BlockingIncidentGrouper (C#), against a stored row. For an unresolvable lock, dmv_blocking_snapshots.contentious_object holds the raw wait resource — e.g. KEY: 6:72057594041991168 (8194443284a0) — whose leading 6 IS the resource database id, but C# cannot turn a database id into a name. The only database name on the row is database_name, which the collector writes as DB_NAME(der_b.database_id): the BLOCKED SESSION's database.
So today:
resource db 6, session db 1
blocked_process_report
Unresolved: key lock, database: StackOverflow2013
dmv_blocking_snapshots (normalized)
Unresolved: key lock, database: master
For the overwhelmingly common same-database lock the two agree and [#1876]'s fix holds. For a genuine cross-database lock they still fingerprint differently — a narrower version of the same defect, in the same place.
The fix, and why it is not a one-liner
DmvBlockingSnapshotCollector already shreds objparse.database_id out of the wait resource for its OBJECT: branch, so the resource database id is in hand server-side. It could emit the full sentinel there — N'Unresolved: ' + LOWER(lock_type) + N' lock, database: ' + ISNULL(DB_NAME(resource_db), N'unknown') — which would arrive already correct, and [#1876]'s normalizer would leave it alone (it is idempotent and a report-form label is a no-op).
What makes it a separate issue:
It only helps new rows. Every DMV row already in the store keeps the raw resource, so the C# approximation has to stay for them regardless — the two mechanisms then coexist and need a stated relationship, rather than one replacing the other.
It has a SQL twin.install/56_collect_dmv_blocking_snapshot.sql is the deprecated Dashboard's byte-identical copy and would have to move with it or the two stores diverge.
It reopens a scope question. The DMV collector deliberately resolves OBJECT: only, with the explicit comment "KEY/PAGE/RID stay raw" — it runs on a much tighter cadence than the blocked-process reader, and the report side's resolution is a per-database cursor. Naming the database is cheap; the tempting adjacent step of resolving the object itself is not, and the two should be decided together.
Not a regression: this is the residue of a fix, and the pre-[#1876] behavior for these rows was strictly worse (a per-lock-hash identity that never deduped at all).
Found while implementing [#1876], and deliberately left out of that PR.
[#1876] made the two blocking collectors'
contentious_objectlabels agree at the incident identity, and in the same change [#1876] corrected theblocked_process_reportsentinel to name the LOCK RESOURCE's database (DB_NAME(resource_database_id)) rather than the event's, because for a cross-database lock those differ and the event's names where the blocked session was merely running.The DMV side's synthesized sentinel does not have that information available where it is built.
Why
The normalizer runs in
BlockingIncidentGrouper(C#), against a stored row. For an unresolvable lock,dmv_blocking_snapshots.contentious_objectholds the raw wait resource — e.g.KEY: 6:72057594041991168 (8194443284a0)— whose leading6IS the resource database id, but C# cannot turn a database id into a name. The only database name on the row isdatabase_name, which the collector writes asDB_NAME(der_b.database_id): the BLOCKED SESSION's database.So today:
blocked_process_reportUnresolved: key lock, database: StackOverflow2013dmv_blocking_snapshots(normalized)Unresolved: key lock, database: masterFor the overwhelmingly common same-database lock the two agree and [#1876]'s fix holds. For a genuine cross-database lock they still fingerprint differently — a narrower version of the same defect, in the same place.
The fix, and why it is not a one-liner
DmvBlockingSnapshotCollectoralready shredsobjparse.database_idout of the wait resource for itsOBJECT:branch, so the resource database id is in hand server-side. It could emit the full sentinel there —N'Unresolved: ' + LOWER(lock_type) + N' lock, database: ' + ISNULL(DB_NAME(resource_db), N'unknown')— which would arrive already correct, and [#1876]'s normalizer would leave it alone (it is idempotent and a report-form label is a no-op).What makes it a separate issue:
install/56_collect_dmv_blocking_snapshot.sqlis the deprecated Dashboard's byte-identical copy and would have to move with it or the two stores diverge.OBJECT:only, with the explicit comment "KEY/PAGE/RID stay raw" — it runs on a much tighter cadence than the blocked-process reader, and the report side's resolution is a per-database cursor. Naming the database is cheap; the tempting adjacent step of resolving the object itself is not, and the two should be decided together.Not a regression: this is the residue of a fix, and the pre-[#1876] behavior for these rows was strictly worse (a per-lock-hash identity that never deduped at all).