Connection pool can briefly exceed max_size when pooling is disabled under load
Maintainer antworten meist innerhalb von 2 Tagen
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 62/100
Rechercherichtung
Lies mssql_python/pybind/connection/connection_pool.cpp und konzentriere dich auf den Fehler-Catch in Phase 3 von ConnectionPool::acquire, closePools() und ConnectionPool::close. Verfolge die Reservierungs- und Bereinigungspfade und untersuche anschließend, wie PR #678 die Connection-Konstruktion geändert hat. Die Aufgabe ist abgeschlossen, wenn ein Regressionstest das Interleaving von Fehler und Deaktivierung abdeckt und die Anzahl aktiver physischer Verbindungen max_size nie überschreitet.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Describe the bug
The connection pool can transiently exceed its configured max_size when pooling is disabled (or the process begins shutting down) while new physical connections are being opened concurrently. The pool's internal reserved-capacity counter (_current_size) can drift below the true number of live connections, after which the pool opens more physical connections than max_size allows. It is transient and self-corrects as connections close.
Root cause: _current_size is a bare counter with no record of which reservation a given decrement belongs to. The failed-open cleanup runs if (_current_size > 0) --_current_size, while a pool disable/close runs _current_size = 0. If a reset lands between a thread reserving a slot and that same thread's open failing, the thread's decrement cancels a different thread's live reservation instead of its own.
Exception message: none. This is a silent _current_size accounting drift, no exception or stack trace.
To reproduce
This is a rare timing race, so it is not deterministically reproducible from a plain script. It requires a new connection to fail to open at the exact moment pooling is disabled or the process is shutting down. The interleave that produces it, with max_size = 2:
import mssql_python
from concurrent.futures import ThreadPoolExecutor
mssql_python.pooling(max_size=2)
# 1. Thread A calls connect(), reserves a slot -> _current_size = 1,
# then starts opening a new physical connection (outside the pool lock).
# 2. Another thread disables pooling: closePools() sets _current_size = 0.
# 3. Thread B calls connect(), reserves the freed slot -> _current_size = 1.
# 4. Thread A's open fails (handle alloc / network error): its cleanup runs
# --_current_size -> 0, cancelling B's slot instead of A's.
# 5. Thread B's open succeeds, but _current_size now reads 0.
# 6. Further connect() calls see room and open past max_size.
Observable symptom while the count is drifted: more live sessions than the configured cap.
SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE login_name = 'yourapp';
-- transiently returns 3 with max_size = 2
Expected behavior
The number of live physical connections should never exceed max_size, regardless of a connection-open failure racing a pooling disable or process shutdown.
Further technical details
Python version: any
SQL Server version: any
Operating system: any. The race is in the cross-platform C++ pool, not platform specific.
Additional context
Area: mssql_python/pybind/connection/connection_pool.cpp, the Phase 3 failure catch in ConnectionPool::acquire, plus closePools() and ConnectionPool::close.
Regression status: pre-existing for the connect()-failure path. PR #678 moved Connection construction out of _mutex (required to fix the #671 deadlock), which widens the same race to also cover constructor failures such as ODBC env init, handle allocation, and OOM. Raised during review of #678.
Proposed fix: give the pool a generation counter. close()/closePools() bumps it under the lock, a reserver snapshots it at ++_current_size, and the failure cleanup only decrements if the generation still matches. This makes the decrement attributable and closes both the constructor and connect paths. Roughly 6 to 8 lines plus a regression test that forces the interleave.
- Vorherrschende Sprache
- Python
- Sterne
- 478
- Forks
- 62
- Ø Merge
- 3 T. 19 Min.
- Gemergte PRs (30 T.)
- 28
Entwicklungsumgebung
Startet den Dev-Container des Projekts im Browser, mit Ihrem eigenen GitHub-Konto.
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus microsoft/mssql-python
-
area: bulk-copy triage needed
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
microsoft/mssql-python#843 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 2 Tagen
-
triage needed
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 35/100
microsoft/mssql-python#846 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 2 Tagen
-
macOS: encrypted connections fail after Homebrew moved the `openssl` alias to `openssl@4`Evtl. vergeben @bewithgaurav hat das vor 16 Tagen übernommen. Offenarea: packaging-platform bug triage needed
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 55/100
microsoft/mssql-python#826 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 2 Tagen
-
Announcement: mssql-python is coming to Django through mssql-django 2.0Evtl. wieder frei @bewithgaurav hat das vor 43 Tagen übernommen, und es ist kein Pull Request offen. Offenannouncement
microsoft/mssql-python#748 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 2 Tagen
-
Decimal in money range still string-binds on the executemany pathEvtl. vergeben @bewithgaurav hat das vor 25 Tagen übernommen. Offenarea: data-types bug triage done under development
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
microsoft/mssql-python#745 · 1 Kommentar · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 2 Tagen
Alle Issues in microsoft/mssql-python
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
UKGovernmentBEIS/control-arena#917 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 88/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
debpalash/VoiceStudio#2937 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
aws-samples/sample-per-model-bedrock#261 ·
Maintainer antworten meist innerhalb von 1 Tag