踩坑:mysqlclient使用utf8mb4字符集乱码问题

159 阅读2分钟
  • 记录一次踩坑,以便寻找共性,总结经验,归纳成方法。

现象

  • 使用mysqlclient去连接数据库,本地环境设置utf8mb4字符集不会生效,在测试环境能够生效。
  • 两个环境运行的代码一致,mysqlclient包版本一致

寻找验证方式

  • 验证建立数据库链接后,字符集是什么
  • 测试环境:
>>>from django.db import connection
>>>cursor = connection.cursor()
>>>cursor.execute("SHOW VARIABLES LIKE 'character_set%';")
8
>>>cursor.fetchall()
(('character_set_client', 'utf8mb4'), ('character_set_connection', 'utf8mb4'), ('character_set_database', 'utf8mb4'), ('character_set_filesystem', 'binary'), ('character_set_results', 'utf8mb4'), ('character_set_server', 'latin1'), ('character_set_system', 'utf8'), ('character_sets_dir', '/usr/share/mysql/charsets/'))

  • 本地环境:
>>>from django.db import connection
>>>cursor = connection.cursor()
>>>cursor.execute("SHOW VARIABLES LIKE 'character_set%';")
8
>>>cursor.fetchall()
(('character_set_client', 'latin1'), ('character_set_connection', 'latin1'), ('character_set_database', 'utf8mb4'), ('character_set_filesystem', 'binary'), ('character_set_results', 'latin1'), ('character_set_server', 'latin1'), ('character_set_system', 'utf8'), ('character_sets_dir', '/usr/share/mysql/charsets/'))

  • 从以上代码输出可以看出本地环境进行数据库连接时,字符集是“latin1”,与预期的utf8mb4不符,导致了中文乱码。

猜想原因

  • 为什么本地环境和测试环境的表现不一致?是什么原因导致的?
  • 猜想1:mysqlclient包版本不一致
    • 使用pip list | grep mysqlclient,发现版本都是2.0.3,排查此原因
  • 猜想2:安装mysqlclient包前,需要安装基础包libmysqlclient-dev,这是由C语言实现的,那是否由该基础包的差异导致的?
    # 测试环境
    flexivsu@po-develop:~$ dpkg -s libmysqlclient-dev | grep Version
    Version: 5.7.42-0ubuntu0.18.04.1
    
    # 本地环境
    news_yu@SZ-YUXINWEN-L1:~$ dpkg -s libmysqlclient-dev | grep Version
    Version: 8.0.33-0ubuntu0.20.04.4
    
    • 使用命令查看发现两个环境的基础包libmysqlclient-dev版本不一致,这应该是兼容性导致的问题

寻找解决方案

  • 在github中github.com/PyMySQL/mys… 的issue栏搜索关键词,寻找出现的问题。最终通过将mysqlclient包从2.0.3升级到2.1.1后,成功解决乱码问题。
  • 经过测试使用2.1.1的mysqlclient可以同时适配5.7和8.0版本的libmysqlclient-dev。