
简介本资源是MySQL官方提供的Python数据库驱动程序mysql-connector-python 2.1.7版本源码发布包面向Python开发者、后端工程师及数据库应用学习者解决Python应用与MySQL数据库原生、合规、稳定交互的核心需求尤其适用于需规避第三方依赖如PyMySQL或要求严格遵循MySQL认证协议如caching_sha2_password的生产环境。压缩包共123个文件主体为90个Python源码文件实现DBAPI接口、连接池、游标逻辑等辅以5个配置文件.cnf用于连接参数定制、10个PEM证书文件支持SSL加密通信以及C扩展相关源码.c/.h/.cc保障性能关键路径效率整体体积11.24MB。目前已有363人下载学习包内结构清晰呈现C-Python混合实现特征含完整异常处理模块、类型映射定义及元数据查询支持可直接编译安装或深入研读底层通信机制是理解数据库驱动原理与定制化开发的优质参考样本。 前阵子接了个内部系统的维护需求服务器是 CentOS 7Python 2.7.5数据库 MySQL 5.7整个环境还只能离线装包。管理员扔给我的安装包就是mysql-connector-python-2.1.7.tar.gz。同事第一反应是“这玩意儿不是pip install mysql-connector一下就完事了吗”话是没错但在一个只能靠离线包过活的老环境里这个 tar.gz 源码包反而成了最稳妥的方案。这篇东西我不打算写成官方文档的翻译就按我实际处理这个包的过程来写它到底是什么、为什么用源码包、安装时有哪些坑、装完怎么连库、以及最常见的报错怎么排查。无论你是刚接触 Python 连 MySQL 的新手还是被老环境折磨的运维/开发应该都能从这里找到能直接抄的答案。1. 先搞清楚这是什么包再动手装1.1 源码包和“一键安装”到底差在哪很多人看到.tar.gz就以为解压就能用其实这是个误解。mysql-connector-python-2.1.7.tar.gz是 MySQL 官方提供的 Python 连接器源码分发包里面装的不是编译好的可执行文件而是 Python 模块的源代码和安装脚本。你把它解压之后会看到setup.py、setup.cfg、README.txt、lib/这些文件其中lib/mysql/目录里才是真正的连接器代码。这里有个关键点MySQL Connector/Python 是纯 Python 实现的数据库驱动它用 Python 直接实现了 MySQL 客户端/服务端通信协议不需要依赖 C 编译器也不需要安装额外的本地库。所以理论上只要机器上能跑对应版本的 Python把这个包里的mysql目录拷到site-packages下面也能用。那为什么还要走setup.py安装因为安装脚本会帮你做三件事检查当前 Python 版本是否兼容、把lib/mysql复制到正确的 site-packages 路径、生成版本信息和 egg-info 元数据。如果跳过这一步手动拷贝后面版本管理和卸载都会很麻烦所以我建议还是老老实实装一遍。1.2 为什么 2.1.7 这个版本足够特别先说结论如果你用的是 Python 3.6 和 MySQL 8.0我不建议你折腾 2.1.7直接用新版连接器就好。但如果你和我一样维护的是 Python 2.7 MySQL 5.7 这种存量环境2.1.7 反而是一个很务实的选择。MySQL Connector/Python 的 2.1.x 系列发布于 2016-2017 年官方支持 Python 2.6、2.7 和 Python 3.3对应的 MySQL 服务端版本覆盖 5.5、5.6、5.7。在那个年代它解决的问题是让 Python 程序不需要装 MySQL C Client Library 就能连接数据库对部署环境非常友好。为什么说这个版本“特别”因为从 MySQL 8.0 开始官方把默认认证插件改成了caching_sha2_password而 2.1.7 这种老版本连接器不认识这个插件。如果你用 2.1.7 去连 MySQL 8.0会直接报Authentication plugin caching_sha2_password is not supported。这个问题在后面的排查部分我会专门展开。所以2.1.7 适合的是老环境的维护场景而不是新项目的选型。2. 安装前必须确认的三件事2.1 Python 版本和连接器版本要匹配安装前我强烈建议你先跑一条命令确认当前 Python 版本python -V我遇到的环境里/usr/bin/python是 2.7.5/usr/bin/python3是 3.6.8两个版本共存。这种多版本环境最坑因为setup.py默认使用你当前PATH里排在前面的那个 Python 解释器。如果你用python setup.py install安装但之后用python3去跑脚本那肯定import mysql.connector失败。我的习惯是先确定业务脚本会用哪个解释器然后用同样的解释器去执行安装。比如业务跑在 Python 2.7 上就用python setup.py install如果跑在 Python 3 上就显式指定python3 setup.py install这一步看似简单但很多人栽在这里。安装完成后最好验证一下解释器路径和模块路径是否一致后面会专门写验证命令。2.2 MySQL 服务端的认证方式决定了你能否连上这是一个很容易被忽略的兼容性问题。MySQL 5.7 及更早版本默认用的认证插件是mysql_native_password2.1.7 支持没问题。但如果你的 MySQL 是 8.0 或更新版本默认新建用户都是caching_sha2_password2.1.7 连不上。如果你确实需要在老环境里连接 MySQL 8.0有两种办法第一种把该用户的认证插件改回mysql_native_passwordALTER USER your_userhost IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;第二种升级连接器到 8.0 以上版本。这里要多说一句别在同一个环境里同时装 2.1.7 和 8.x两者都会往site-packages/mysql写文件很容易互相覆盖最后import到的版本完全不可控。2.3 你有没有 root 权限安装路径的选择setup.py install默认会把模块装到系统 Python 的site-packages目录比如/usr/lib/python2.7/site-packages/这个位置通常需要 root 权限。如果你没有管理员权限或者不想污染系统 Python 环境可以用--user参数python setup.py install --user这条命令会把模块装到当前用户目录下例如~/.local/lib/python2.7/site-packages/。之后运行 Python 脚本时当前用户默认能加载到这个路径不需要额外配置PYTHONPATH。如果你在虚拟环境里直接激活虚拟环境再安装就行虚拟环境会自己隔离路径。这里我建议新手优先考虑虚拟环境能避免绝大多数的环境冲突问题。3. 完整安装实操从解压到看到版本号3.1 下载、校验与解压离线环境下拿到 tar.gz 后第一步不是解压而是校验文件完整性。用官方提供的校验和比对一下md5sum mysql-connector-python-2.1.7.tar.gz sha1sum mysql-connector-python-2.1.7.tar.gz然后用tar解压tar zxvf mysql-connector-python-2.1.7.tar.gz cd mysql-connector-python-2.1.7解压后建议先看一下目录结构我用tree -L 2扫过一遍里面核心的就几个东西lib/mysql/是源码主体setup.py是安装入口README.txt里写了基本的连接示例。如果目录里有tests/那是官方自带的测试用例有时间可以跑一下没时间跳过也不影响。我习惯在解压后先看一下版本信息确认包没拿错python setup.py --version如果输出2.1.7就说明这个包确实是我们要装的那个。3.2 执行安装三种模式怎么选安装模式取决于你的实际权限和部署需求。第一种系统级安装适用于有 root 权限的服务器sudo python setup.py install安装过程中会输出类似这样的日志running install running build running build_py creating build/lib ... copying build/lib/mysql/connector/__init__.py - /usr/lib/python2.7/site-packages/mysql/connector ... writing list of installed files to /usr/lib/python2.7/site-packages/mysql_connector_python-2.1.7.egg-info看到writing list of installed files这行说明安装已经完成。这行日志很重要后面卸载的时候要依赖它。第二种用户级安装适用于没有 root 权限或不想动系统环境的情况python setup.py install --user第三种安装到指定目录适用于自定义部署路径python setup.py install --prefix/opt/python-packages--prefix模式需要你手动把/opt/python-packages加进PYTHONPATH环境变量或者用.pth文件来扩展搜索路径配置成本高一些非必要不推荐。3.3 验证安装结果安装完必须验证这一步别偷懒。跑一条命令确认版本号python -c import mysql.connector; print(mysql.connector.__version__)如果输出2.1.7说明模块能正常导入版本也对。如果报错ImportError: No module named mysql.connector先不要慌按下面几步排查which python python -c import sys; print(sys.path)先确认当前python指向哪个解释器再确认site-packages路径是否在sys.path里。很多时候是因为which python指向了/usr/local/bin/python而模块装到了/usr/bin/python的目录里。我还习惯检查一下 site-packages 下的实际文件ls /usr/lib/python2.7/site-packages/ | grep mysql正常情况下应该能看到一个mysql/目录和一个mysql_connector_python-2.1.7.egg-info目录。如果只有 egg-info 而没有mysql/说明安装过程中途出错了需要重新执行安装。4. 接入业务第一个能跑的连接示例4.1 连接参数逐个说明模块装好之后下一步就是建立连接。我先给你一个最基础、最完整的连接示例import mysql.connector conn mysql.connector.connect( host127.0.0.1, port3306, userblog_user, passwordyour_password, databaseblog_db, charsetutf8mb4, use_unicodeTrue, autocommitFalse, connect_timeout5 ) cursor conn.cursor() cursor.execute(SELECT VERSION()) row cursor.fetchone() print(MySQL version:, row[0]) cursor.close() conn.close()我解释一下几个容易被忽略的参数host建议写127.0.0.1而不是localhost。原因在于某些系统上localhost会被解析成 socket 连接如果你没配 socket 文件路径连接会失败。用 TCP 连接方式写 IP 最省事。charset和use_unicode我建议总是显式设置。老环境里如果忘了配字符集中文写入后查出来可能是乱码问题排查起来非常痛苦。utf8mb4能覆盖 emoji 和生僻字比utf8更推荐。autocommit默认是 False也就是说每次execute修改数据后都要手动commit()否则事务不会真正提交。如果你的业务里每条语句都希望立即生效就在连接参数里把autocommitTrue打开。养成显式声明这个参数的习惯能避免“查不到刚插入的数据”这种诡异问题。4.2 增删改查的标准姿势连接建立后日常操作基本就是增删改查但写法上有个重要原则永远使用参数化查询不要用字符串拼接 SQL。import mysql.connector conn mysql.connector.connect( host127.0.0.1, userblog_user, passwordyour_password, databaseblog_db, autocommitTrue ) cursor conn.cursor() # 插入 cursor.execute( INSERT INTO articles (title, content) VALUES (%s, %s), (MySQL Connector/Python 实战, 正文内容……) ) print(insert_id:, cursor.lastrowid) # 查询 cursor.execute(SELECT id, title FROM articles WHERE title LIKE %s, (%MySQL%,)) rows cursor.fetchall() for row in rows: print(row[0], row[1]) # 更新 cursor.execute( UPDATE articles SET content %s WHERE id %s, (新的正文内容……, 1) ) # 删除 cursor.execute(DELETE FROM articles WHERE id %s, (999,)) cursor.close() conn.close()注意%s是占位符不是字符串格式化。这个风格和%运算符有点像但意义完全不同。使用参数化查询的好处有两个一是避免 SQL 注入二是让驱动自动处理类型转换和转义比如字符串里的引号不会被粗暴截断。如果一条 SQL 执行出错connector 会抛出mysql.connector.errors里的异常。你可以捕获并打印出来from mysql.connector import Error try: cursor.execute(SELECT * FROM not_exist_table) except Error as e: print(Error:, e)4.3 连接池高并发场景下的首选方案如果你的服务是 Web 接口频繁创建和关闭连接会很浪费握手开销。这时候用连接池更合适from mysql.connector import pooling db_pool mysql.connector.pooling.MySQLConnectionPool( pool_nameblog_pool, pool_size5, host127.0.0.1, userblog_user, passwordyour_password, databaseblog_db, autocommitTrue ) conn db_pool.get_connection() cursor conn.cursor() cursor.execute(SELECT COUNT(*) FROM articles) print(cursor.fetchone()[0]) cursor.close() conn.close()pool_size我一般习惯设为 5 到 10不要一味贪大。因为每个连接都会占用服务端的线程和内存资源池子设太大容易造成数据库连接数被打满。另外从池子里拿连接用完后调用close()不是真正断开而是把连接归还给池子这点和普通连接的行为不一样写代码的时候别搞混了。5. 常见问题排查我把能踩的坑都替你踩了一遍5.1 No module named mysql.connector这个问题出现频率最高原因却各不相同。我整理三种典型情况第一种安装和执行脚本用的是不同 Python。比如你用python装了模块却用python3跑脚本。解决办法是统一解释器。第二种虚拟环境没激活。如果你在系统 Python 里装了模块然后激活虚拟环境后跑脚本虚拟环境默认是隔离的找不到系统里的包。反过来也一样。第三种安装了但文件不完整。比如安装日志里没有出现copying build/lib/mysql/connector/__init__.py这类行说明安装其实中断了。重新执行安装命令注意看输出内容。我个人的排查顺序是先which python再python -c import sys; print(sys.path)最后看 site-packages 下有没有mysql/目录。5.2 Authentication plugin caching_sha2_password is not supported这个报错我在前面提过是 2.1.7 连接 MySQL 8.0 时的典型问题。2.1.7 发布的时候 MySQL 8.0 还没正式普及所以根本不认识caching_sha2_password这个默认认证插件。解决办法有两个方向改用户认证方式或者换连接器版本。如果你只有 2.1.7 可用那就登录 MySQL执行ALTER USER blog_user% IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;注意执行完之后需要重新连接之前建立的事务连接不会自动生效。这个办法作为应急方案没问题但长期维护还是建议升级连接器。5.3 卸载和版本残留问题setup.py install安装的包卸载没有统一的uninstall命令。好在安装日志里记录了所有安装的文件列表安装结束后会生成一个install_record.txt或者打印出来。如果你找得到这个记录可以用xargs rm -rf清理但我不建议手动删容易误伤其他包。更稳妥的办法是直接删除 site-packages 下的mysql/目录和mysql_connector_python-2.1.7.egg-info目录rm -rf /usr/lib/python2.7/site-packages/mysql rm -rf /usr/lib/python2.7/site-packages/mysql_connector_python-2.1.7.egg-info如果你是通过 pip 安装的卸载很简单pip uninstall mysql-connector注意 2.1.x 在 PyPI 上的包名是mysql-connector不是mysql-connector-python。从 8.0 版本开始包名才改成mysql-connector-python。这个差异经常导致新版文档里的卸载命令在老包上执行时报“包不存在”。下面是一个常见问题速查表方便你直接对照问题现象可能原因解决方案No module named mysql.connectorPython 解释器不一致或安装未完成统一解释器重新安装并验证版本号Authentication plugin caching_sha2_password is not supported2.1.7 不支持 MySQL 8.0 默认认证修改用户认证插件或升级连接器Access denied for user xxxlocalhost账号密码错误或 host 限制检查用户授权确认连接 hostUnknown database xxx数据库不存在创建库或修改配置Connection refused服务端未启动、端口不对、防火墙拦截检查 MySQL 状态、端口监听和防火墙规则中文乱码字符集配置不对连接参数加charsetutf8mb4确认库表字符集6. 后来我又总结的几点经验折腾完这套老环境之后我把自己的一些实操习惯整理了一下算是给后来人提个醒。第一离线装包时尽量把 tar.gz 源码包和对应的依赖一起归档。很多时候你以为只要一个连接器就够了结果后来发现还要配其他模块又得跑一遍流程。我现在的做法是在requirements.txt旁边放一个packages/目录把安装包按版本号归档好方便后续复现。第二安装完驱动之后第一时间写一个最小验证脚本打印版本号和数据库版本。这一步只要花十秒钟但能确认 Python、驱动、MySQL 三者之间的连通性。等出了问题再回头查环境成本高得多。第三连接参数里charset和use_unicode一定要显式声明我见过太多因为默认字符集不对导致中文乱码的案例。数据库连接是典型的“配置一时爽排查火葬场”的环节一开始就写清楚比事后补救强一百倍。第四老项目尽量别混用 pip 和setup.py install。这两种方式装的包路径可能不一样互相覆盖后版本状态很难说清。我踩过这个坑最后只好把 site-packages 里的 mysql 目录删掉重装了一遍才恢复正常。最后再分享一个小技巧如果你在一个刚配置好的测试环境里想在几分钟内快速验证连接器和数据库的兼容性可以用 Python 的-c参数直接跑一段一次性代码不需要建任何脚本文件python -c import mysql.connector; connmysql.connector.connect(host127.0.0.1,userroot,password123456); print(conn.get_server_info()); conn.close()如果这行命令能输出数据库版本号说明整条链路已经通了后面写业务代码就不用再怀疑环境问题了。本文还有配套的精品资源点击获取