Skip to content

Merge dev to main: add ProtectSession watchdog#796

Merged
erikdarlingdata merged 2 commits into
mainfrom
dev
May 23, 2026
Merged

Merge dev to main: add ProtectSession watchdog#796
erikdarlingdata merged 2 commits into
mainfrom
dev

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Adds ProtectSession, a non-canonical helper procedure that watches one designated session and decides what to do with whoever is blocking it.

What is in this PR

  • ProtectSession/ProtectSession.sql -- the procedure (~770 lines)
  • ProtectSession/README.md -- usage docs, parameter table, classification details

Not added to Install-All; intentional, this is a non-canonical helper.

Highlights

Classification is held-lock-based, not command-based. sys.dm_tran_locks is the source of truth for "is this blocker durably modifying permanent data" -- checking command would misclassify SELECT INTO dbo.RealTable (looks like a SELECT), and a session whose current statement is a SELECT but whose transaction still holds X locks from an earlier UPDATE. The proc looks for modification or schema-change locks (X / IX / U / SIX / BU / Sch-M) on OBJECT resources outside tempdb.

Default behavior: kill SELECT blockers and tempdb-only modifications past @block_threshold_seconds; leave permanent-data modifications alone. Override with @kill_modification_blockers = 1 (kill them anyway, rolls back their work) or @abort_on_modification_block = 1 (kill the protected session instead).

Chain-walk diagnostics. Each cycle walks the blocking chain upstream to capture chain_depth + lead_blocker_session_id -- surfaced in @debug output and in every kill/abort message. The KILL target stays the immediate blocker, since that is the only kill that directly frees the protected session.

Contended-resource naming. From sys.dm_tran_locks for the protected session's WAIT row: database name, resource type, and object name (for OBJECT-type contention).

Spid-reuse defense. SQL Server recycles freed session_ids aggressively (confirmed empirically: 6 fresh connections all got the same recycled spid in sequence). The proc fingerprints sessions by (session_id, login_time) and re-verifies before any KILL, skipping with a log message on mismatch rather than misfiring on a recycled spid.

🤖 Generated with Claude Code

erikdarlingdata and others added 2 commits May 23, 2026 10:15
A non-canonical helper procedure that watches one designated session and
decides what to do with whoever is blocking it. Classification reads
sys.dm_tran_locks (not blocker.command), so SELECT-INTO-permanent and
sessions that ran an UPDATE before their current statement are correctly
identified as modifications. By default only reads and tempdb-only
modifications are killed; permanent-data modifications are spared unless
@kill_modification_blockers = 1 (kill them anyway) or
@abort_on_modification_block = 1 (kill the protected session instead).

Walks the blocking chain upstream for chain_depth + lead_blocker_session_id
diagnostics; KILL target stays the immediate blocker. Resolves the
contended resource (database + type + object name when OBJECT) for the
debug output and kill/abort message.

Defends against spid-reuse misfires by fingerprinting (session_id,
login_time) and re-verifying before any KILL.

Not added to Install-All; non-canonical helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Picks up cead18b (PR #794 merge) and cea63fe (auto-rebuilt Install-All)
so the upcoming dev->main PR only contains the new ProtectSession files
and does not inadvertently revert the Install-All rebuild.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit 07996ac into main May 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant