Resolving "Unread Result Found" Error in Python MySQL Connector: Application of Buffered Cursors

Nov 26, 2025 · Programming · 10 views · 7.8

Keywords: Python | MySQL connector | Buffered cursor | Unread result error | Database query

Abstract: This article provides an in-depth analysis of the "Unread result found" error encountered when using the Python MySQL connector, which typically occurs when unread result sets remain after query execution with non-buffered cursors. Through a practical case of JSON data insertion, it explains the root cause of the error and presents a solution using buffered cursors (buffered=True). Additionally, it compares the working principles, applicable scenarios, and performance impacts of buffered versus non-buffered cursors, aiding developers in better understanding and applying advanced features of the MySQL connector.

Problem Background and Error Analysis

During development, many Python developers using the mysql.connector library to interact with MySQL databases may encounter the mysql.connector.errors.InternalError: Unread result found error. This error typically arises when a new operation is attempted after executing a query without fully reading the result set. For instance, in a loop that executes multiple SELECT queries and uses the fetchone() method to retrieve single rows, if remaining results are not handled, subsequent database operations trigger this exception.

Core Issue: Result Set Handling with Non-Buffered Cursors

The MySQL connector defaults to non-buffered cursors, meaning query results are not immediately fetched from the server to the client but are loaded on demand. When fetchone() is called, only the first row of the result set is retrieved, leaving the remaining rows on the server. If a new query is executed with the same cursor at this point, the connector detects unread results and throws the "Unread result found" error. This behavior ensures data consistency and resource efficiency but can cause confusion in development.

Solution: Using Buffered Cursors

By setting the cursor to buffered mode, the entire result set is fetched at once and cached in client memory. Thus, row-fetching methods like fetchone() read from the local buffer without leaving unread results. Implementation involves specifying the buffered=True parameter when creating the cursor, e.g., cursor = cnx.cursor(buffered=True). This approach is straightforward and effective for queries with small result sets.

Code Example and Optimization

The following improved code example demonstrates how to apply buffered cursors to resolve the original issue. Suppose there is a JSON data parsing and insertion process that requires multiple database queries to associate parent and child data:

import mysql.connector

# Establish database connection
cnx = mysql.connector.connect(
    host="localhost",
    user="username",
    password="password",
    database="mydatabase"
)

# Create a buffered cursor
cursor = cnx.cursor(buffered=True)

# Assume result is data parsed from JSON
for steps in result['routes'][0]['legs'][0]['steps']:
    query = 'SELECT leg_no FROM leg_data WHERE travel_mode = %s AND Orig_lat = %s AND Orig_lng = %s AND Dest_lat = %s AND Dest_lng = %s AND time_stamp = %s'
    
    if steps['travel_mode'] == "pub_tran":
        travel_mode = steps['travel_mode']
        Orig_lat = steps['var_1']['dep']['lat']
        Orig_lng = steps['var_1']['dep']['lng']
        Dest_lat = steps['var_1']['arr']['lat']
        Dest_lng = steps['var_1']['arr']['lng']
        time_stamp = leg['_sent_time_stamp']
    elif steps['travel_mode'] == "a_pied":
        travel_mode = steps['travel_mode']
        Orig_lat = steps['var_2']['lat']
        Orig_lng = steps['var_2']['lng']
        Dest_lat = steps['var_2']['lat']  # Note: Dest_lat and Dest_lng same as Orig here; adjust per logic
        Dest_lng = steps['var_2']['lng']
        time_stamp = leg['_sent_time_stamp']
    
    # Execute query
    cursor.execute(query, (travel_mode, Orig_lat, Orig_lng, Dest_lat, Dest_lng, time_stamp))
    
    # Fetch result
    result_row = cursor.fetchone()
    if result_row:
        leg_no = result_row[0]
        print(leg_no)
    else:
        print("No matching record found")

# Close cursor and connection
cursor.close()
cnx.close()

In this example, using a buffered cursor ensures that each fetchone() call does not leave unread results, thus avoiding the error. Additionally, error handling is incorporated to manage cases where the query returns no results.

Comparison of Buffered and Non-Buffered Cursors

The primary advantage of buffered cursors is simplified result set handling, especially for scenarios requiring multiple accesses to results or combining several queries. However, they may increase memory usage, particularly with large result sets. Non-buffered cursors are more resource-efficient but require developers to explicitly handle all results, e.g., via fetchall() or iterative reading. The choice depends on specific application needs: buffered cursors are ideal for small result sets with frequent operations, while non-buffered cursors may be more efficient for large datasets.

Performance Considerations and Best Practices

When using buffered cursors, be mindful of memory overhead. Excessively large result sets can lead to performance degradation or out-of-memory errors. It is advisable to monitor resource usage during development and adjust strategies based on data volume. For example, non-buffered cursors with row-by-row reading might be more suitable for paginated queries or streaming processing. Additionally, ensure timely closure of cursors and connections to release database resources.

Conclusion

The "Unread result found" error is a common issue in the Python MySQL connector, rooted in the result set handling mechanism of non-buffered cursors. By using the buffered=True parameter to create buffered cursors, this problem can be easily resolved while enhancing code readability and robustness. Developers should weigh the trade-offs between buffered and non-buffered cursors based on practical scenarios to achieve efficient database interactions.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.