1

我在 settings.py 中使用具有以下配置的 Django

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '-',
        'USER': '-',
        'PASSWORD': '-',
        'HOST': '-',
        'PORT': '-',
        'OPTIONS': {'charset': 'utf8mb4'}
    }
}

db 服务器在 AWS RDS 上运行。我有两个 EC2 实例,其中一个能够运行完全相同的代码并获取相同的数据,而从第二个 EC2 我收到此错误:

     return self._execute_with_wrappers(sql  params  many=False  executor=self._execute)
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/utils.py"   line 75  in _execute_with_wrappers  
     return executor(sql     params  many    context)
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/utils.py"   line 84  in _execute    
     return self.cursor.execute(sql  params)        
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/mysql/base.py"  line 73  in execute 
     return self.cursor.execute(query    args)      
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 206     in execute 
     res = self._query(query)           
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 321     in _query  
     self._post_get_result()            
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 355     in _post_get_result    
self._rows = self._fetch_row(0)         
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 328     in _fetch_row  
     return self._result.fetch_row(size  self._fetch_type)      
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 180: invalid start byte

django html 响应还显示了这一点:

Unicode error hint
The string that could not be encoded/decoded was: \n<p>�&lt;/p>\

此外,负责引发错误的代码片段是:

    exp = MyModel.objects.all()
    **for e in exp:** <-- this line is throwing the error
        #do something

两台服务器上的版本:

EC2-1st具有:

Ubuntu 16.04.4

Django==1.11.2
mysqlclient==1.3.10
django-mysql==2.1.0

python3 --version
Python 3.5.2

mysql --version
mysql  Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using  EditLine wrapper

EC2-2nd 是 EC2-1st 的副本,并应用了更新:

Ubuntu 20.04.3

Django==3.2.6
mysqlclient==2.0.3
django-mysql==3.10.0

python3 --version
Python 3.9.5

mysql --version
mysql  Ver 14.14 Distrib 5.7.35, for Linux (x86_64) using  EditLine wrapper

此外,我的本地服务器能够使用这些版本的工具正常运行:[我已经使用接近 prod 配置的本地配置在本地导入了 RDS db,以尝试调试问题]。

Mac OS 11.5.2
Django==3.2.6
mysqlclient==2.0.3
django-mysql==3.10.0

Python 3.9.6

mysql  Ver 8.0.25 for macos11.3 on x86_64 (Homebrew)

我应该尝试什么?

4

1 回答 1

0

MySQL 文档连接时错误处理描述了当您使用 MySQL 8.0 客户端库连接到具有 utf8mb4 字符集的 MySQL 5.7 服务器时出现的问题。MySQL 8.0 客户端请求 utf8mb4_0900_ai_ci 排序规则,但 MySQL 5.7 服务器无法识别该排序规则,因此服务器静默回退到具有 latin1_swedish_ci 排序规则的 latin1 字符集。随后服务器发送 latin1 结果集,但客户端认为它正在接收 utf8mb4,最终导致UnicodeDecodeError. 作为一种解决方法,您必须明确地SET NAMES utf8mb4. 我创建了一个问题mysqlclient#504来要求 python 客户端每次都这样做。

要在连接后确认字符集不正确,请仔细检查服务器的值character_set_client(解释语句的character_set_connection字符集)、(语句转换为的字符集)和character_set_results(发送结果集的字符集)。如果它们latin1尽管客户端以 utf8mb4 连接,则可能触发了此错误。

with con.cursor() as c:
  c.execute("show variables like 'character_set_%'")
  for row in c:
    print(row)
(b'character_set_client', b'latin1')
(b'character_set_connection', b'latin1')
(b'character_set_database', b'latin1')
(b'character_set_filesystem', b'binary')
(b'character_set_results', b'latin1')
(b'character_set_server', b'latin1')
(b'character_set_system', b'utf8')
(b'character_sets_dir', b'/usr/share/mysql/charsets/')

我相信该问题的解决方法是在连接后执行以下操作:

# explicitly set connection charset to the same as MySQLdb.connect()
con.query("SET NAMES utf8mb4")
con.store_result()
于 2021-10-07T18:41:27.410 回答