Skip to content

SQLRDD: refresh the lock table on a connection of its own - #2135

Merged
RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-lock-timer-v2
Oct 28, 2026
Merged

RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-lock-timer-v2

Conversation

@ecosSystem

Copy link
Copy Markdown
Contributor

The RDD refreshes its rows in the lock table on a System.Timers.Timer. The timer event runs on a thread pool thread, but it used the connection of the application, which may be executing a statement on the main thread at the same moment. An ADO.NET connection must not be used by two threads at once: when the timer met a running statement, either side could fail at random.

We saw it while importing a large customer dataset into SQL Server. Two statements of the import failed for no visible reason:

  • ExecuteNonQuery erfordert eine geöffnete und verfügbare Connection (requires an open and available connection) on a CREATE INDEX,
  • Der angegebene Schlüssel war nicht im Wörterbuch angegeben (the given key was not present in the dictionary) while reading the column list.

What changed

  • The timer refreshes the lock table on a short-lived connection of its own (same provider and connection string), so it never touches the connection of the application.
  • With UseLocks off, the timer does nothing: no locks are written, so there is nothing to refresh.
  • A failure of the refresh is written to the debug output instead of being raised on the thread pool thread.

Testing

  • The import that failed (297 tables, about 86 million rows, more than two hours) ran twice more without any connection error.
  • Our ERP runs with UseLocks off, where the timer now does nothing. With UseLocks on, a record lock, a write and the unlock on one connection work as before. Locks of other users and the refresh after the timer interval were not tested separately.

🤖 Generated with Claude Code

Every connection starts a System.Timers.Timer that refreshes its entries in
the lock table every 120 seconds. The timer runs on a thread pool thread but
used the connection of the application, and an ADO.NET connection must not
be used by two threads at once. With short statements this rarely collided;
importing a large dataset it did reliably: a refresh during a CREATE INDEX on
a 1.1 million row table made the index fail with "ExecuteNonQuery requires an
open and available Connection", and a following metadata query returned
nothing.

The refresh now opens a connection of its own (pooled), and it is skipped
when UseLocks is off, as nothing is written to the lock table then. Errors
of the refresh no longer escape the timer thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst
RobertvanderHulst merged commit c55cfd0 into X-Sharp:dev Oct 28, 2026
1 check 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.

2 participants