Blog Post

SQL Server Blog
3 MIN READ

mssql-python 1.6: Unblocking Your Threads

DavidLevy's avatar
DavidLevy
Icon for Microsoft rankMicrosoft
Apr 24, 2026

The last two mssql-python releases shipped big features: Bulk Copy in 1.4 for high-throughput data loading, and Apache Arrow in 1.5 for zero-copy analytics. Version 1.6 is about what happens next: you take those features into production, scale up your thread pool, and find out where the driver was quietly holding you back.

This release unblocks your threads during connection setup, fixes crashes and incorrect results in common cursor patterns, and hardens security for passwords with special characters and log file paths.

 

pip install --upgrade mssql-python

Your threads can run while connections are opening

If you're running mssql-python behind Flask, FastAPI, Django, or any WSGI/ASGI server with thread-based workers, this one matters.

Opening a database connection is slow. There's DNS resolution, a TCP handshake, TLS negotiation, and SQL Server authentication. In previous versions, every other Python thread in your process was frozen while that happened, because the driver held the Global Interpreter Lock (GIL) during the entire operation. One thread opening a connection meant no other thread could serve requests, process data, or do anything at all.

Version 1.6 releases the GIL during connect and disconnect. Your other threads keep running while the network round-trip completes. If you have a multi-threaded web server handling concurrent requests, this removes a serialization bottleneck you may not have realized you had.

The connection pool was also reworked to stay safe under this change. Previously, the pool held an internal lock while calling connect, which would have created a deadlock now that connect releases the GIL. The pool now reserves a slot first, connects outside the lock, and rolls back the reservation if the connection fails.

Decimal parameters work with setinputsizes

If you use cursor.setinputsizes() to declare parameter types for performance-sensitive batch inserts, you may have hit a crash when specifying SQL_DECIMAL or SQL_NUMERIC. This is fixed. Decimal values now bind correctly whether you're using execute() or executemany():

cursor.setinputsizes([
    (mssql_python.SQL_WVARCHAR, 100, 0),
    (mssql_python.SQL_INTEGER, 0, 0),
    (mssql_python.SQL_DECIMAL, 18, 2),
])

cursor.executemany(
    "INSERT INTO Products (Name, CategoryID, Price) VALUES (?, ?, ?)",
    [
        ("Widget", 1, Decimal("19.99")),
        ("Gadget", 2, Decimal("29.99")),
    ],
)

Iterating catalog results with fetchone()

If you've used cursor.tables(), cursor.columns(), or other catalog methods and tried to walk the results with fetchone(), you may have gotten incorrect data. Row tracking was broken for catalog result sets. This now works the way you'd expect:

cursor.tables(tableType="TABLE")
while True:
    row = cursor.fetchone()
    if row is None:
        break
    print(row.table_name)

This also applies to primaryKeys(), foreignKeys(), statistics(), procedures(), and getTypeInfo().

Reusing prepared statements without reset

If you call cursor.execute() with reset_cursor=False to reuse a prepared statement across calls, this no longer raises an "Invalid cursor state" error.

Passwords with special characters stay masked in logs

If your SQL Server password contains semicolons, braces, or other ODBC-special characters (e.g., PWD={Top;Secret}), previous versions could accidentally leak part of it in sanitized log output. The password masking logic has been rewritten to correctly handle all ODBC connection string formats. If the connection string can't be parsed at all, the entire string is now redacted rather than partially exposed.

The logging system also now rejects log file paths that attempt directory traversal, preventing setup_logging(log_file_path="../../somewhere/else.log") from writing outside the intended directory.

Better type checker support for executemany

If your type checker flagged executemany() when you passed dictionaries as parameter rows, that warning is gone. The type annotations now correctly accept Mapping types, matching the DB API 2.0 spec for named parameters.

Get started

pip install --upgrade mssql-python

For questions or issues, file them on GitHub or email mssql-python@microsoft.com.

Published Apr 24, 2026
Version 1.0
No CommentsBe the first to comment