Django 项目配置 MySQL 8.0 实战指南:完整步骤与避坑技巧

首先需要明确一个关键前提:Django 3.2 及以上版本确实原生支持 MySQL 8.0,但这并不意味着开箱即用。真正导致配置失败的原因,往往是几个容易忽略的细节——认证插件兼容性、驱动选择、字符集设置以及 SQL 模式定义。下面我们直接切入核心,逐一拆解常见的卡点与对应的解决方案。
检查 MySQL 8.0 默认认证插件是否与 Django 兼容
Django 3.2+ 能够正常连接 MySQL 8.0,但有一个硬性条件:MySQL 用户不能使用 caching_sha2_password 认证插件。这是 MySQL 8.0 的默认认证方式,而 Django(包括它所依赖的 mysqlclient)仅支持 mysql_native_password。
如果跳过此步骤,最典型的现象就是遇到以下错误:django.db.utils.OperationalError: (1045, "Access denied for user 'myuser'@'localhost' (using password: YES)")。密码明明正确,却始终无法连接,根本原因就在于认证插件不匹配。
解决方法并不复杂,按顺序执行以下命令即可:
- 登录 MySQL:
mysql -u root -p - 执行:
ALTER USER 'myuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 执行:
FLUSH PRIVILEGES; - 验证:查询
SELECT host, user, plugin FROM mysql.user WHERE user = 'myuser';,确认plugin列的值显示为mysql_native_password
安装并配置 mysqlclient(推荐,而非 PyMySQL)
Django 官方推荐且性能更优的 MySQL 驱动是 mysqlclient,它基于 C 扩展编译,与 MySQL 原生协议贴合更紧密。虽然 PyMySQL 为纯 Python 实现、pip install 即可安装,但在 MySQL 8.0 的部分特性上存在短板,例如某些 JSON 函数支持不完整,高并发场景下性能表现也不够理想。
安装前需要确保系统级依赖齐全:
- Ubuntu/Debian:
sudo apt-get install python3-dev default-libmysqlclient-dev build-essential - macOS(Homebrew):
brew install mysql-client,然后设置环境变量export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH" - 接着运行
pip install mysqlclient
如果编译仍然失败,请先检查 mysql_config 是否在 $PATH 中,或者使用 mysql_config --version 确认输出为 8.0.x 版本。这一步卡住的人很多,多半是路径没有配置正确。
修改 Django 的 DATABASES 配置
settings.py 中的 DATABASES 字典必须显式指定 ENGINE 和 OPTIONS,否则容易触发隐式编码问题或连接超时。以下是一份经过验证的最小可用配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject_db',
'USER': 'myuser',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4',
},
'TEST': {
'CHARSET': 'utf8mb4',
'COLLATION': 'utf8mb4_unicode_ci',
}
}
}
有几个关键点值得专门强调:
charset和TEST.CHARSET必须设置为utf8mb4,否则 emoji 或四字节 UTF-8 字符会被截断甚至直接报错init_command能有效预防 MySQL 8.0 严格模式下常见的Field 'xxx' doesn't have a default value错误HOST不要使用localhost——它会触发 Unix socket 连接,可能绕过 TCP 配置导致不可控;改用127.0.0.1更加可靠
执行 migrate 前务必检查 MySQL 全局配置
很多时候 migrate 失败,问题并不在 Django 代码,而是 MySQL 服务端的限制。建议运行前先进入 MySQL 做一轮检查:
SHOW VARIABLES LIKE 'sql_mode';—— 如果模式中包含NO_ZERO_DATE或NO_ZERO_IN_DATE,Django 3.2+ 中DateField(null=True)可能报错。建议只保留STRICT_TRANS_TABLESSHOW VARIABLES LIKE 'max_allowed_packet';—— 如果小于 64M,包含 BLOB 字段等大 migration 文件可能会中途中断SELECT @@collation_database;—— 应为utf8mb4_unicode_ci,否则新建表默认排序规则不一致
这些参数需要在 /etc/mysql/my.cnf(Linux)或 /usr/local/etc/my.cnf(macOS)中持久化设置。仅在 session 级别修改的话,重启后就会失效。
最后补充一点:MySQL 8.0 的权限模型更加细粒度,推荐使用 GRANT ALL PRIVILEGES ON myproject_db.* TO 'myuser'@'127.0.0.1'; 而非 GRANT ALL ON *.*,这样既安全,也能避免因权限缓存导致的偶发拒绝连接。
