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的游标中存在未读取的结果集,导致后续查询无法执行。结合你的代码来看:
- executemany未清空结果:在
runQuery的批量执行分支中,注释掉了self.__cursor.fetchall(),而某些场景下executemany会返回结果(比如调用带输出的存储过程、或使用支持RETURNING的MySQL扩展),未读取的结果会残留游标中。 - 非缓冲游标特性:如果使用的是非缓冲游标(默认可能为False),当执行查询后未读取完所有结果,直接执行下一个查询就会触发该错误。
- 前置查询残留:如果在Update操作之前有未处理完的SELECT或其他返回结果的查询,也会导致结果集残留。
解决方案
启用executemany后的结果读取
把runQuery中被注释的self.__cursor.fetchall()取消注释,确保批量执行后清空游标缓冲区:for composite in composites: self.__cursor.executemany(sql, composite) # 清空游标结果缓冲区 self.__cursor.fetchall()使用缓冲游标
在创建数据库游标时,指定buffered=True,这样结果会被缓冲到本地,避免结果残留问题:self.__cursor = self.__connection.cursor(buffered=True)确保所有查询结果都被处理
检查所有执行查询的代码,只要是返回结果的操作(如SELECT),必须通过fetchall()、fetchone()或fetchmany()读取完所有结果后,再执行下一个数据库操作。检查生成的Update语句
确认框架生成的Update语句是否包含RETURNING子句(部分MySQL插件或版本支持),如果有,需要在执行Update后读取返回的结果集。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

