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
{{ message }}
Repository navigation
Commit 21187de
Browse filesBrowse the repository at this point in the historyBrowse files
FIX: Bound pooled connection checkout on unresponsive sockets (#859)
### Work Item / Issue Reference
<!--
IMPORTANT: Please follow the PR template guidelines below.
For mssql-python maintainers: Insert your ADO Work Item ID below
For external contributors: Insert Github Issue number below
Only one reference is required - either GitHub issue OR ADO Work Item.
-->
<!-- mssql-python maintainers: ADO Work Item -->
<!-- External contributors: GitHub Issue -->
> GitHub Issue: #854
-------------------------------------------------------------------
### Summary
<!-- Insert your summary of changes below. Minimum 10 characters
required. -->
Bound pooled connection reset and autocommit configuration using a
temporary native connection timeout. Use the positive login timeout
(explicit attrs_before takes precedence), or a 15-second validation
default, and restore the previous connection timeout on success. After
validation fails, open a replacement rather than probing every stale
idle socket sequentially. Preserve isolation/transaction cleanup and
document that cancellation, cleanup, and replacement login can add time:
this is not an end-to-end connect deadline.
Add stalled-socket regressions covering both autocommit modes, one/three
stale sockets, timeout precedence, the finite default, and timeout
restoration. Extend isolation reset coverage to SQL SET statements and
adjust close-error mocks to inject failures after construction.
Validation (Linux x64, Python 3.13, SQL Server 2022):
- `bash build.sh` and subsequent `cmake --build
/work/mssql_python/pybind/build --config Release -j2`: passed; rebuilt
native extension used for testing.
- `python -m pytest -v --tb=short`: 5,537 passed, 167 skipped, 42
deselected. Linux test copy used LF shell scripts to avoid Windows
checkout CRLF failures.
- `python -m pre_commit run black-check --all-files --hook-stage
pre-push`: passed.
- Actual TCP DROP reproduction: approximately 3 seconds with timeout=1
for one/three stale connections in both autocommit modes; replacement
queries succeeded.
- Windows/macOS validation not run. An initial combined packet-drop run
exited with code 139; isolated and repeated runs subsequently passed,
but the initial crash was not conclusively explained.
<!--
### PR Title Guide
> For feature requests
FEAT: (short-description)
> For non-feature requests like test case updates, config updates ,
dependency updates etc
CHORE: (short-description)
> For Fix requests
FIX: (short-description)
> For doc update requests
DOC: (short-description)
> For Formatting, indentation, or styling update
STYLE: (short-description)
> For Refactor, without any feature changes
REFACTOR: (short-description)
> For performance improvements
PERF: (short-description)
> For AI tooling, agents, skills, prompts, or AI-assisted development
workflows
AI: (short-description)
> For release related changes
RELEASE: #<RELEASE_VERSION> (short-description)
### Contribution Guidelines
External contributors:
- Create a GitHub issue first:
https://github.com/microsoft/mssql-python/issues/new
- Link the GitHub issue in the "GitHub Issue" section above
- Follow the PR title format and provide a meaningful summary
mssql-python maintainers:
- Create an ADO Work Item following internal processes
- Link the ADO Work Item in the "ADO Work Item" section above
- Follow the PR title format and provide a meaningful summary
-->
Fixes: #854
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: README.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,6 +129,10 @@ EntraID authentication is now fully supported on MacOS and Linux but with certai
129
129
130
130
The Microsoft mssql_python driver provides built-in support for connection pooling, which helps improve performance and scalability by reusing active database connections instead of creating a new connection for every request. This feature is enabled by default. For more information, refer [Connection Pooling Wiki](https://github.com/microsoft/mssql-python/wiki/Connection#connection-pooling).
131
131
132
+
Pooled checkout validates and resets a reused connection with a temporary native connection timeout. It uses the positive login timeout from `connect(timeout=N)` or, with higher precedence, `attrs_before[SQL_ATTR_LOGIN_TIMEOUT]`; if neither specifies a positive value, validation uses 15 seconds. A failed validation discards that candidate and attempts a new physical connection instead of probing every idle socket sequentially. The previous connection timeout is restored after successful checkout, and query timeouts remain controlled separately by `conn.timeout`. These are driver operation timeouts, not a strict end-to-end `connect()` deadline: cancellation/cleanup and a replacement login can add time. Pool return still requires network I/O and is not bounded by the checkout validation timeout.
133
+
134
+
This favors bounded validation latency over trying every idle connection during a single checkout. If the replacement login fails, that checkout raises a connection exception even if a healthy idle connection remains; the healthy connection stays pooled and can be reused by a subsequent checkout.
135
+
132
136
> **Interactive / Device-code authentication in multi-user processes:** For `ActiveDirectoryInteractive` and `ActiveDirectoryDeviceCode`, the driver caches one credential instance per authentication type for the lifetime of the process so that pooled reconnects refresh silently instead of re-prompting. As a result, every interactive connection opened in the same process shares that one signed-in account — the first user to authenticate. If your application serves multiple end users from a single process, do **not** rely on interactive/device-code auth to isolate them; instead supply your own per-user token via a token provider so each user's connection is keyed to their own identity.
133
137
134
138
> **Bring-your-own token (`token_provider` / raw access token):** When you supply your own access token (via a token provider or a raw token in `attrs_before`), managing its lifetime is **your application's responsibility**. The driver stores a pooled connection under the identity that opened it, but it cannot refresh a token it did not mint. If a pooled connection is reused after its token has expired, the reconnect (ODBC's implicit connection resiliency) will fail. Ensure your token provider returns a currently-valid token on every call, and account for token expiry in your own logic. The driver's built-in expiry-aware checkout (refreshing a pooled connection whose token is near expiry) only applies to Managed Identity and interactive/device-code pools, whose tokens the driver can silently re-mint — not to bring-your-own tokens.
0 commit comments