【问题标题】:Is there a way to use 'pool_reset_connection' from mysql-connector-python with MariaDB 10.4.7?有没有办法将 mysql-connector-python 中的“pool_reset_connection”与 MariaDB 10.4.7 一起使用?
【发布时间】:2020-01-22 11:09:03
【问题描述】:

我想将我的 python 程序从普通连接更改为连接池,以便在几个小时内没有发送查询时数据库连接不会丢失,并且数据库不会被一堆查询淹没使用高峰期。

我正在使用 Python 3.7.4、mysql-connector-python 8.0.17 和 MariaDB 10.4.7。 当我使用普通连接时它工作正常,但 MariaDB 显然不支持 mysql.connector.pooling.MySQLConnectionPoolpool_reset_session 设置

在我的代码开始时,它会尝试创建尚不存在的数据库,这导致了我得到的错误。

import mysql.connector as mariadb
from mysql.connector import errorcode
from mysql.connector import pooling

cnx = mariadb.pooling.MySQLConnectionPool(user='root', password='password', host='localhost', 
                                          pool_name='connectionpool', pool_size=10, pool_reset_session=True)

try:
    db = cnx.get_connection()
    cursor = db.cursor()
    cursor.execute("CREATE DATABASE IF NOT EXISTS tests")
    print("Created database")
except mariadb.Error as err:
    print(f"Failed creating database: {err}")
finally:
    print("Finally (create)")
    db.close()

我希望这个 sn-p 只会创建数据库 tests,但我得到了以下两个错误:

mysql.connector.errors.NotSupportedError: MySQL version 5.7.2 and earlier does not support COM_RESET_CONNECTION.

还有

mysql.connector.errors.OperationalError: 1047 (08S01): Unknown command

从追溯日志来看,这似乎是由于尝试在第 17 行执行 db.close() 而引起的。

带有回溯的完整输出: https://pastebin.com/H3SAvA9N

我在问我能做些什么来解决这个问题,以及是否有可能在 MariaDB 10.4.7 中使用这种连接池(我很困惑,因为它说 MySQL

我还发现 MariaDB Connector/J 确实提供了这样一个选项,称为 useResetConnection,但我不想仅仅为了这个功能而学习 Java。

【问题讨论】:

    标签: python-3.x mariadb mysql-connector-python


    【解决方案1】:

    将服务器版本升级到 10.0 时,MariaDB 必须为服务器版本添加前缀以避免破坏复制(复制协议需要一位数的主要版本号,有关详细信息,请查看此answer)。

    无论您使用 MariaDB 10.0 还是 10.4,MySQL Connector/Python 将始终返回版本号 5.5.5:

    >>> conn= mysql.connector.connect(user="foo")
    >>> print(conn.get_server_version())
    (5, 5, 5)
    >>> cursor=conn.cursor()
    >>> cursor.execute("select version()")
    >>> row=cursor.fetchone()
    >>> print(row)
    ('10.4.7-MariaDB-log',)
    

    COM_RESET_CONNECTION 重置服务器端的连接是在 MariaDB 10.2 中引入的,因此要使其正常工作,您必须更改 MySQL 连接器/Python 的代码,例如在 _check_server_version (abstracts.py) 中:

    
    +        if server_version.startswith("5.5.5-")
    +            server_version= server_version[6:]
    

    这当然不是通用解决方案,因为它不适用于 10.2 之前的 MariaDB 版本。在检查 MariaDB 不支持的某些功能(例如 X-Protocol)时,它可能还会产生不良的副作用。

    【讨论】:

    • 如果我所做的只是向 MariaDB 服务器查询标准 SQL 查询,我会不会遇到这些不良的副作用?比如SELECTUPDATECREATE等等?
    • 对于“正常”语句和使用主要 api 调用(如 PEP-249 中所述),不应该有不良的副作用。仅供参考:MariaDB 也在开发一个新的 MariaDB Connector for Python ,第一个 GA 将在未来几个月内推出。
    • 真的吗?我不知道。我将在上面尝试您的答案的解决方案,看看它是否适合我的目的。在看到 Java 已经拥有自己的之后,我会非常期待 MariaDB/Python 连接器
    • 当然,如果您有错误的逻辑,例如不释放未读结果集(在使用未缓冲结果集后不关闭游标),则连接将不可重用。顺便说一句,您使用什么版本的 C/Python?
    • 如果你的意思是我的 Python 版本,我在 Windows 上使用的是 3.7.4 x64 版本(我对 Python 和所有这些东西还是很陌生,所以如果我误解了你的问题,我深表歉意)不久前,我已经以艰难的方式学到了有关未使用结果的教训:-D
    【解决方案2】:

    正如@Georg Richter 指出的那样,MariaDB 出于历史原因返回一个版本,例如 "5.5.5-10.4.10-MariaDB-1:10.4.10+maria~bionic-log"

    MySQL python 连接器显式检查版本 (https://github.com/mysql/mysql-connector-python/blob/b034f25ec8037f5d60015bf2ed4ee278ec12fd17/lib/mysql/connector/connection.py#L1157),由于 MariaDB 服务器显示为版本 5.5.5,因此引发错误。

    从 MariaDB 10.2.6 开始,您可以将version 显式添加到 cnf 文件的 [server] 部分。

    配置如下:

    [server]
    . . . 
    version=5.7.99-10.4.10-MariaDB
    

    连接器将看到版本 5.7.99,并采取相应的行为。

    【讨论】:

    • 像魅力一样工作。我使用 MariaDB 10.3.22 作为从属服务器,MySQL 5.7.29 作为主服务器。在我将版本添加到 MariaDB 服务器中的 cnf 文件后,此配置有效。非常感谢。
    • 有效。刚刚编辑 /etc/my.csv 并添加了上面的行,然后重新启动了服务。
    • @vikaskv,你是说 /etc/my.cnf 吗?无论我尝试哪个文件,我都无法让这个解决方案发挥作用。
    【解决方案3】:

    我在使用 mariaDB 的 mysql-connector-python 时遇到了同样的问题,我将 mysql-connector-python 版本降级到 8.0.12,它对我有用

    【讨论】:

    • 此线程中唯一可行的解​​决方案。将版本降级到 8.0.12,问题消失了。
    • 当我尝试关闭来自连接池的连接时,我也收到了1047 (08S01): Unknown command。我使用的是 8.0.19 版本。我尝试了 8.0.12 到 8.0.19 之间的所有版本,它在 8.0.17 开始出现问题(即未知命令错误),所以我选择了 8.0.16。
    猜你喜欢
    • 2019-12-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 2016-11-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多