You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python MySQL Connector执行Update时出现Unread result found错误排查

Python MySQL Connector "Unread result found" 错误排查与解决

使用公司内部框架执行简单Update操作时,触发了Python MySQL Connector的Unread result found错误。已尝试直接执行SQL语句(在DBMS中可正常运行,但代码中无效),也尝试过设置错误非阻塞,但后续Select操作仍会触发相同错误,需要明确错误原因并获取解决方案。

相关代码

业务代码

bene.salarie_id = beneficaire.salarie_id
benef.beneficiaire_pj = pj
benef.beneficiaire_ss = beneficaire.beneficiaire_ss
benef.beneficiaire_type = beneficaire.beneficiaire_type
benef.beneficiaire_noemie = beneficaire.beneficiaire_noemie
benef.beneficiaire_cv = beneficaire.beneficiaire_cv   
benef.update()
logging.info('Mise à jour du bénéficiaire réussie')

Update方法实现

"""Mise à jour d'un modèle dans la base de données.

  Args:
  column (Union[str, tuple], optional): La ou les colonnes à prendre en compte. Par défaut None.
clause (Union[Clause, tuple], optional): Le ou les types de clause. Par défaut Clause.EQUAL.
"""
reflection = Reflection(self)
query = Query().update(reflection.getTable(), reflection.getColumns(), Reflection.generateMark(reflection.getValues()))
where, values = self.__findClause(column, clause)
self.__runOn(Query(f'{query} {where}'), reflection.getValues() + values, reflection)
logging.info('Mise à jour d\'un modèle dans la base de données.')

__runOn方法

def __runOn(self, query : Query, parameters : tuple = (), reflection : Reflection = None) -> Connection:
    """Exécute une requête sur la base de données liée au modèle.

    Args:
        query (Query): La requête à exécuter.
        parameters (tuple, optional): Les paramètres de la requête. Par défaut, la liste est vide.
        reflection (Reflection, optional): La réflexion existante du modèle. Par défaut None.
        
    Returns:
        Connection: La connexion à la base de données.
    """
    if reflection is None:
        reflection = Reflection(self)
    connection = Connection.getInstance(reflection.getDatabase())
    connection.runQuery(query, parameters)
    return connection

runQuery方法

def runQuery(self, query : Query, parameters : Union[tuple, Any] = ()) -> 'Connection':
"""Exécute une requête SQL.

Args:
    query (Query): Objet de requête.
    parameters  (Union[tuple, Any], optional): Liste des paramètres de la requête. Par défaut, la liste est vide.

Returns:
    Connection: Instance de connexion à la base de données.
"""
logging.info(f'Exécution de la requête \"{query}\"...')
if type(parameters) is not tuple:
    parameters = (parameters,)
config = self.getConfigurations()
count = len(parameters)
hastimer = config.hasTimer()
sql = str(query)
start, stop = 0, 0
if count == 0 or type(parameters[0]) is not tuple:
    logging.info(f'Paramètres de la requête \"{parameters}\"...')
    if hastimer: start = time()
    self.__cursor.execute(sql, parameters)
    if hastimer: stop = time()
else:
    logging.info(f'Exécution multiple, paramètres non affichables...')
    size = config.getMaxpacket()
    lenght = round(size / len(parameters[0]))
    composites = [ parameters[x:x+lenght] for x in range(0, count, lenght) ]
    if hastimer: start = time()
    for composite in composites:
        self.__cursor.executemany(sql, composite)
        #faire un fetchall pour vider le buffer
        # self.__cursor.fetchall()
    if hastimer: stop = time()
logging.info(f'Exécution de la requête terminée.')
if hastimer:
    seconds = round(stop - start, 3)
    logging.info(f'Temps d\'exécution de la requête : {seconds} secondes.')
return self

错误原因分析

Unread result found错误本质是MySQL Connector的游标中存在未读取的结果集,导致后续查询无法执行。结合你的代码来看:

  1. executemany未清空结果:在runQuery的批量执行分支中,注释掉了self.__cursor.fetchall(),而某些场景下executemany会返回结果(比如调用带输出的存储过程、或使用支持RETURNING的MySQL扩展),未读取的结果会残留游标中。
  2. 非缓冲游标特性:如果使用的是非缓冲游标(默认可能为False),当执行查询后未读取完所有结果,直接执行下一个查询就会触发该错误。
  3. 前置查询残留:如果在Update操作之前有未处理完的SELECT或其他返回结果的查询,也会导致结果集残留。

解决方案

  1. 启用executemany后的结果读取
    把runQuery中被注释的self.__cursor.fetchall()取消注释,确保批量执行后清空游标缓冲区:

    for composite in composites:
        self.__cursor.executemany(sql, composite)
        # 清空游标结果缓冲区
        self.__cursor.fetchall()
    
  2. 使用缓冲游标
    在创建数据库游标时,指定buffered=True,这样结果会被缓冲到本地,避免结果残留问题:

    self.__cursor = self.__connection.cursor(buffered=True)
    
  3. 确保所有查询结果都被处理
    检查所有执行查询的代码,只要是返回结果的操作(如SELECT),必须通过fetchall()、fetchone()或fetchmany()读取完所有结果后,再执行下一个数据库操作。

  4. 检查生成的Update语句
    确认框架生成的Update语句是否包含RETURNING子句(部分MySQL插件或版本支持),如果有,需要在执行Update后读取返回的结果集。

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:22:38