Как подключить MySQL к Django
Как подключить MySQL или MariaDB к Django: версии для Django 6.x, mysqlclient и PyMySQL, DATABASES с utf8mb4, перенос с SQLite, Docker и частые ошибки.
Содержание · 11 разделов
- Какие версии MySQL и MariaDB поддерживает Django
- Установите MySQL-сервер
- Создайте базу и пользователя
- Выберите драйвер: mysqlclient или PyMySQL
- Установка mysqlclient
- Ошибки сборки mysqlclient
- PyMySQL вместо mysqlclient
- Настройте DATABASES
- localhost или 127.0.0.1
- OPTIONS: кодировка, sql_mode и уровень изоляции
- Постоянные соединения
- Проверьте подключение
- Перенос данных с SQLite на MySQL
- Особенности MySQL, которые стоит учесть
- Сравнение строк без учёта регистра
- Миграции не откатываются при сбое
- Ограничение длины индекса
- Таблицы часовых поясов
- Движок хранения InnoDB
- MySQL и Django в Docker
- Частые ошибки подключения
- Error loading MySQLdb module. Did you install mysqlclient?
- Can’t connect to server (2002 или 2003)
- Access denied for user ‘mysite’@‘localhost’ (1045)
- Unknown database ‘mysite’ (1049)
- Incorrect string value for column (1366)
- MySQL server has gone away (2006)
- Частые вопросы
- Что выбрать для Django: MySQL или PostgreSQL?
- Почему тесты падают с Access denied к базе test_mysite?
- Как подключить Django к существующей базе MySQL?
- Как сделать резервную копию базы MySQL?
- Нужен ли пакет django-mysql?
- Итог
Чтобы подключить MySQL к Django, установите драйвер mysqlclient, создайте в MySQL базу с кодировкой utf8mb4 и отдельного пользователя, затем укажите их в DATABASES с движком django.db.backends.mysql и выполните python manage.py migrate. MariaDB подключается точно так же — у неё общий с MySQL бэкенд.
pip install mysqlclient
# config/settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "mysite",
"USER": "mysite",
"PASSWORD": "надёжный-пароль",
"HOST": "127.0.0.1",
"PORT": "3306",
}
}
Ниже — подробно: какие версии MySQL нужны Django 5.2 и 6.x, как выбрать между mysqlclient и PyMySQL и что делать, если драйвер не собирается. Отдельно разобраны OPTIONS (sql_mode, init_command), перенос данных со SQLite, отличия MySQL, которые ломают проекты после переезда, и запуск в Docker. Общие принципы настройки базы описаны в статье «Базы данных в Django».
Какие версии MySQL и MariaDB поддерживает Django
Требования к серверу и драйверу растут с каждым релизом Django:
| Django | MySQL | MariaDB | mysqlclient |
|---|---|---|---|
| 5.2 LTS | 8.0.11 и новее | 10.5 и новее | 1.4.3 и новее |
| 6.0 | 8.0.11 и новее | 10.6 и новее | 2.2.1 и новее |
| 6.1 | 8.4 и новее | 10.11 и новее | 2.2.1 и новее |
Django 6.1 отказался от MySQL 8.0, потому что поддержка этой ветки у Oracle закончилась в апреле 2026 года. Учитывайте это при выборе сервера: в Ubuntu 24.04 из стандартного репозитория ставится MySQL 8.0.46. С Django 5.2 и 6.0 он работает, а Django 6.1 при первом подключении остановится с ошибкой:
django.db.utils.NotSupportedError: MySQL 8.4 or later is required (found 8.0.46).
Решения: MySQL 8.4 из официального APT-репозитория MySQL или из Docker, MariaDB 10.11 из того же репозитория Ubuntu 24.04 либо переход на Ubuntu 26.04, где в репозитории уже MySQL 8.4.
Установите MySQL-сервер
- Windows — MSI-пакет MySQL Community Server 8.4 LTS с dev.mysql.com. После установки откроется MySQL Configurator: в нём задаётся пароль пользователя
root. - Ubuntu/Debian —
sudo apt install mysql-server(Ubuntu 26.04) илиsudo apt install mariadb-server(Ubuntu 24.04, Debian 12 и 13). - macOS —
brew install mysqlиbrew services start mysql.
Для разработки сервер удобнее поднять в Docker — одна команда, нужная версия и никаких следов в системе:
docker run --name mysql-dev -e MYSQL_ROOT_PASSWORD=devroot -e MYSQL_DATABASE=mysite -e MYSQL_USER=mysite -e MYSQL_PASSWORD=devpass -p 3306:3306 -d mysql:8.4
Образ сам создаст базу mysite и пользователя mysite с правами на неё, так что следующий раздел можно пропустить.
Создайте базу и пользователя
Не подключайте Django от имени root. Откройте консоль MySQL:
# Ubuntu/Debian: root входит через системного пользователя, без пароля
sudo mysql
# Windows и macOS
mysql -u root -p
Создайте базу и пользователя:
CREATE DATABASE mysite CHARACTER SET utf8mb4;
CREATE USER 'mysite'@'localhost' IDENTIFIED BY 'надёжный-пароль';
GRANT ALL PRIVILEGES ON mysite.* TO 'mysite'@'localhost';
CHARACTER SET utf8mb4 обязателен: старая кодировка utf8 в MySQL — это трёхбайтовая utf8mb3, в ней не помещаются эмодзи и часть иероглифов. Сопоставление (collation) сервер выберет сам: в MySQL 8.4 это utf8mb4_0900_ai_ci.
Пользователь в MySQL — это пара «имя и хост». 'mysite'@'localhost' может подключаться только с той же машины. Если Django работает на другом сервере или в контейнере, создайте пользователя для его адреса или для любого хоста — 'mysite'@'%'. Выйти из консоли — exit.
Выберите драйвер: mysqlclient или PyMySQL
Django общается с MySQL через DB-API драйвер. Подходят три пакета:
| Драйвер | Устройство | Поддержка в Django | ENGINE |
|---|---|---|---|
| mysqlclient | C-расширение | Официальная, рекомендуемый вариант | django.db.backends.mysql |
| PyMySQL | Чистый Python | Неофициальная, через режим совместимости | django.db.backends.mysql |
| MySQL Connector/Python | Пакет Oracle | Собственный бэкенд от Oracle | mysql.connector.django |
Берите mysqlclient: адаптер для него входит в Django, и документация рекомендует именно этот драйвер. PyMySQL нужен, когда mysqlclient не удаётся собрать: на виртуальном хостинге без компилятора, в AWS Lambda, в минимальных образах. Connector/Python поставляется со своим адаптером, который, как предупреждает документация Django, может не поддерживать самые новые релизы фреймворка.
Установка mysqlclient
Ставьте драйвер в виртуальное окружение проекта.
Windows. На PyPI есть готовые колёса (wheel) для 64-битного Python 3.10–3.15, поэтому достаточно одной команды:
pip install mysqlclient
Ubuntu/Debian. Готовых сборок под Linux нет — pip компилирует пакет, и ему нужны заголовки Python, клиентская библиотека и pkg-config:
sudo apt install python3-dev default-libmysqlclient-dev build-essential pkg-config
pip install mysqlclient
В Red Hat, CentOS и Fedora нужны пакеты python3-devel, mysql-devel и pkgconfig.
macOS. Через Homebrew:
brew install mysql-client pkg-config
export PKG_CONFIG_PATH="$(brew --prefix)/opt/mysql-client/lib/pkgconfig"
pip install mysqlclient
Если MySQL-сервер уже установлен через brew install mysql, mysql-client и PKG_CONFIG_PATH не нужны — хватит brew install pkg-config.
Проверьте установку:
python -c "import MySQLdb; print(MySQLdb.version_info)"
# → (2, 3, 0, 'final', 0)
Пакет называется mysqlclient, а модуль — MySQLdb: это продолжение старой библиотеки MySQLdb с поддержкой Python 3.
Ошибки сборки mysqlclient
Windows: fatal error C1083: Cannot open include file: 'mysql.h'. Pip не нашёл готового колеса и попытался собрать пакет из исходников. Так бывает с 32-битным Python и со старой версией mysqlclient, закреплённой в requirements.txt. Проверьте разрядность интерпретатора:
python -c "import struct; print(struct.calcsize('P') * 8)"
# → 64
Если выводится 32, поставьте 64-битный Python. Обновите pip (python -m pip install -U pip) и снимите жёсткую привязку к старой версии драйвера. Собирать mysqlclient на Windows вручную (MariaDB Connector/C плюс Visual Studio Build Tools) имеет смысл только в крайнем случае — проще перейти на PyMySQL.
Linux и macOS: Can not find valid pkg-config name. Не установлен pkg-config или пакет разработчика клиентской библиотеки. Поставьте pkg-config и default-libmysqlclient-dev (на macOS — pkg-config и mysql-client). Если библиотека лежит в нестандартном месте, передайте флаги сборки через переменные MYSQLCLIENT_CFLAGS и MYSQLCLIENT_LDFLAGS.
Python.h: No such file or directory или command 'gcc' failed. Нет компилятора или заголовков Python: установите build-essential и python3-dev.
PyMySQL вместо mysqlclient
PyMySQL написан на чистом Python и ставится везде без компиляции:
pip install "PyMySQL[rsa]"
Дополнение [rsa] устанавливает пакет cryptography. Он нужен для caching_sha2_password — способа аутентификации, который MySQL 8 использует по умолчанию. Без него подключение упадёт с ошибкой RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods.
Django ищет модуль MySQLdb, поэтому PyMySQL нужно выдать за него. Сделайте это в начале settings.py — так подмена сработает для всех точек входа: manage.py, Gunicorn, Celery:
# config/settings.py
import pymysql
pymysql.install_as_MySQLdb()
ENGINE остаётся прежним — django.db.backends.mysql.
PyMySQL 1.1.3 и новее представляется mysqlclient версии 2.2.8 и проходит проверку версии в Django 6.x. Со старым PyMySQL Django откажется запускаться:
django.core.exceptions.ImproperlyConfigured: mysqlclient 2.2.1 or newer is required; you have 1.4.6.
Обновите PyMySQL. Если обновить нельзя, перед install_as_MySQLdb() подмените номер версии: pymysql.version_info = (2, 2, 1, "final", 0). Учтите, что официально Django PyMySQL не поддерживает: в большинстве проектов он работает без проблем, но ошибки совместимости исправлять придётся самим.
Настройте DATABASES
Полная настройка с паролем из переменных окружения:
# config/settings.py
import os
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": os.environ.get("MYSQL_DATABASE", "mysite"),
"USER": os.environ.get("MYSQL_USER", "mysite"),
"PASSWORD": os.environ["MYSQL_PASSWORD"],
"HOST": os.environ.get("MYSQL_HOST", "127.0.0.1"),
"PORT": os.environ.get("MYSQL_PORT", "3306"),
"OPTIONS": {
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
},
"CONN_MAX_AGE": 60,
"CONN_HEALTH_CHECKS": True,
}
}
Пароль читается без значения по умолчанию: если переменная не задана, проект упадёт при старте с KeyError, а не подключится с неверными данными. Задать переменные можно так:
# macOS/Linux
export MYSQL_PASSWORD="надёжный-пароль"
# Windows PowerShell
$env:MYSQL_PASSWORD = "надёжный-пароль"
Как хранить такие значения в .env и разделять настройки разработки и продакшна, рассказано в статье о settings.py в Django.
| Ключ | Значение |
|---|---|
ENGINE | django.db.backends.mysql — для MySQL и MariaDB, с mysqlclient и PyMySQL |
NAME | Имя базы данных |
USER | Пользователь MySQL |
PASSWORD | Его пароль |
HOST | 127.0.0.1, IP, имя сервиса в Docker или путь к сокету, начинающийся с / |
PORT | 3306 по умолчанию; пустая строка — тоже порт по умолчанию |
OPTIONS | Параметры, которые Django передаёт драйверу при подключении |
CONN_MAX_AGE | Сколько секунд держать соединение между запросами; 0 — закрывать сразу |
localhost или 127.0.0.1
С mysqlclient на Linux и macOS значение "HOST": "localhost" означает подключение через Unix-сокет, а не по TCP. Если сокет лежит не там, где его ищет клиентская библиотека, появится ошибка Can't connect to local MySQL server through socket. Адрес 127.0.0.1 всегда ведёт по TCP. Подключаться через сокет намеренно можно, указав путь к нему: "HOST": "/var/run/mysqld/mysqld.sock".
OPTIONS: кодировка, sql_mode и уровень изоляции
charset. Начиная с Django 5.2 соединение по умолчанию использует utf8mb4, поэтому "charset": "utf8mb4" в OPTIONS больше не нужен. Указывайте "charset": "utf8mb3" только для старой базы, которую нельзя конвертировать.
sql_mode. Строгий режим (STRICT_TRANS_TABLES) превращает предупреждения MySQL в ошибки: слишком длинная строка не обрежется молча, а вызовет исключение. В MySQL 8.4 он включён по умолчанию, но хостинг может переопределить sql_mode. Тогда Django выдаст предупреждение:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
Строка init_command из примера выше включает строгий режим для каждого соединения. Учтите, что SET sql_mode=... заменяет весь список режимов, а не дополняет его. Тот же параметр подходит для других команд при подключении, например SET default_storage_engine=INNODB.
isolation_level. Django по умолчанию переключает соединение на уровень изоляции read committed, хотя MySQL использует repeatable read. С repeatable read возможна потеря данных: get_or_create() выбрасывает IntegrityError, а следующий get() объект не находит. Менять значение ключа "isolation_level" в OPTIONS без веской причины не стоит.
read_default_file. Параметры подключения можно хранить в конфигурационном файле MySQL вместо settings.py:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"OPTIONS": {"read_default_file": "/etc/mysql/django.cnf"},
}
}
# /etc/mysql/django.cnf
[client]
database = mysite
user = mysite
password = надёжный-пароль
default-character-set = utf8mb4
Значения из OPTIONS важнее NAME, USER и других ключей, а те, в свою очередь, важнее файла.
Постоянные соединения
Встроенного пула соединений для MySQL в Django нет — он есть только для PostgreSQL и Oracle. Повторно использовать соединения позволяет CONN_MAX_AGE: значение 60 держит соединение минуту. CONN_HEALTH_CHECKS: True проверяет его перед запросом, если сервер успел закрыть соединение, например после перезапуска. При запуске через ASGI постоянные соединения лучше отключить.
Проверьте подключение
python manage.py migrate
Django создаст таблицы и выведет Applying ... OK для каждой миграции. Что происходит при migrate и как работать с миграциями дальше, разобрано в статье «Миграции в Django». База новая, поэтому затем создайте администратора командой createsuperuser.
В Django 6.1 подключение проверяет и python manage.py check: команда теперь проверяет все базы из DATABASES. Если сервер недоступен, вы увидите ошибку подключения. В Django 5.2 и 6.0 то же самое делает python manage.py check --database default.
Консоль MySQL с параметрами из настроек открывает python manage.py dbshell — для этого в PATH должен быть клиент mysql.
Перенос данных с SQLite на MySQL
Данные переносятся через фикстуры Django. Сначала выгрузите их, пока проект работает со SQLite:
python manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission -e admin.LogEntry -e sessions --indent 2 -o data.json
Типы контента (contenttypes) и права (auth.Permission) Django создаёт сам при migrate, поэтому их исключают из выгрузки, а ссылки на них сохраняют по естественным ключам (--natural-*). Журнал админки и сессии переносить не обязательно.
Важно: сохраняйте файл через
-o data.json. В Windows PowerShell 5.1 перенаправление> data.jsonзаписывает файл в UTF-16, иloaddataего не прочитает.
Затем переключите DATABASES на MySQL, создайте таблицы и загрузите данные:
python manage.py migrate
python manage.py loaddata data.json
На этом шаге всплывают различия двух СУБД — SQLite прощает то, что MySQL отвергает:
Data too long for column— SQLite не проверяетmax_length, и в базе могли накопиться строки длиннее лимита. Строгий режим MySQL их не пропустит: найдите такие записи и сократите их до выгрузки.Duplicate entry ... for key— уникальность в SQLite учитывает регистр, а в MySQL нет. ПользователиAdminиadminспокойно жили в SQLite, но в MySQL это дубликат. Подробнее — в разделе о регистре ниже.
Для баз в несколько гигабайт фикстуры слишком медленные. Такие объёмы переносят специализированными инструментами, а dumpdata оставляют для небольших проектов.
Особенности MySQL, которые стоит учесть
Django скрывает большую часть различий между СУБД, но не все. Эти отличия чаще всего ломают проект после переезда.
Сравнение строк без учёта регистра
Сопоставление utf8mb4_0900_ai_ci не различает регистр (ci — case-insensitive) и диакритику (ai — accent-insensitive). Поэтому User.objects.filter(username="admin") найдёт и Admin, уникальное поле не примет aa, если в таблице уже есть AA, а «ё» и «е» при сравнении совпадут. В MariaDB сопоставления по умолчанию тоже регистронезависимые.
Если для поля нужно точное сравнение, задайте ему двоичное сопоставление через db_collation:
from django.db import models
class Promo(models.Model):
code = models.CharField(max_length=32, unique=True, db_collation="utf8mb4_bin")
utf8mb4_bin есть и в MySQL, и в MariaDB. После изменения выполните makemigrations и migrate. Учтите и обратную сторону: формсеты Django проверяют уникальность с учётом регистра, поэтому при регистронезависимом сопоставлении значения aa и AA пройдут валидацию формы, но save() выбросит IntegrityError.
Миграции не откатываются при сбое
PostgreSQL и SQLite выполняют миграцию в одной транзакции: при ошибке все изменения схемы откатываются. MySQL не поддерживает транзакции для DDL — команд, которые меняют структуру таблиц. Если миграция упала на середине, первые операции уже применены, и Django не может вернуть базу в прежнее состояние.
Что помогает:
- Делайте миграции небольшими: одна логическая правка схемы — одна миграция. Миграции данных держите отдельно от изменений схемы.
- Перед
migrateв продакшне делайте резервную копию черезmysqldump. - Если миграция упала, вручную верните или доделайте изменения в базе. Когда схема совпадает с ожидаемой, отметьте миграцию применённой без выполнения:
python manage.py migrate blog 0005 --fake.
Изменения структуры больших таблиц к тому же могут блокировать их на время, пропорциональное числу строк, — планируйте такие миграции на период низкой нагрузки.
Ограничение длины индекса
В utf8mb4 символ занимает до 4 байт, а ключ индекса InnoDB ограничен 3072 байтами. Уникальное поле CharField(max_length=1000, unique=True) требует до 4000 байт, и миграция упадёт с ошибкой Specified key was too long; max key length is 3072 bytes. Для составных индексов и UniqueConstraint длины полей складываются.
Django заранее предупреждает об уникальных строковых полях длиннее 255 символов:
blog.Post.slug: (mysql.W003) MySQL may not allow unique CharFields to have a max_length > 255.
TextField в MySQL нельзя сделать уникальным: длина у поля не задана, а MySQL индексирует только начало значений типов TEXT и BLOB. Используйте CharField с разумным max_length.
Таблицы часовых поясов
При USE_TZ = True (значение по умолчанию в новых проектах) функции TruncDate, ExtractYear и фильтры вроде __date переводят время в текущий часовой пояс на стороне базы. Для этого в MySQL должны быть загружены таблицы часовых поясов. Без них такие запросы возвращают None или пустой результат. Загрузить таблицы нужно один раз на сервер:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
В Windows системной базы часовых поясов нет — MySQL предлагает готовый SQL-пакет на странице загрузок dev.mysql.com. Официальные Docker-образы MySQL и MariaDB загружают таблицы сами при первом запуске.
Движок хранения InnoDB
Django не указывает движок при создании таблиц, поэтому они получают движок сервера по умолчанию — в MySQL 8 это InnoDB с транзакциями и внешними ключами. Старый MyISAM не поддерживает ни то ни другое: transaction.atomic() молча перестаёт что-либо откатывать. На старом хостинге проверьте движок командой SHOW TABLE STATUS; в dbshell.
MySQL и Django в Docker
Связка для разработки: MySQL 8.4 и Django в одном compose.yaml.
services:
db:
image: mysql:8.4
environment:
MYSQL_DATABASE: mysite
MYSQL_USER: mysite
MYSQL_PASSWORD: devpass
MYSQL_ROOT_PASSWORD: devroot
volumes:
- mysql_data:/var/lib/mysql
- ./docker/mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', '127.0.0.1']
interval: 5s
timeout: 5s
retries: 20
web:
build: .
command: sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
environment:
MYSQL_HOST: db
MYSQL_DATABASE: mysite
MYSQL_USER: mysite
MYSQL_PASSWORD: devpass
ports:
- '8000:8000'
depends_on:
db:
condition: service_healthy
volumes:
mysql_data:
Пояснения к файлу:
MYSQL_HOST: db— внутри контейнераlocalhostуказывает на сам контейнерweb, а до MySQL можно добраться только по имени сервиса.- Проверка готовности.
depends_onсservice_healthyждёт, пока MySQL начнёт принимать соединения. Пинг идёт на127.0.0.1, то есть по TCP: при первом запуске образ инициализирует базу на временном сервере без сети, и проверка через сокет успела бы пройти раньше времени. - Папка
docker/mysql-init. SQL-файлы из неё выполняются один раз, при создании тома. Туда удобно положить выдачу прав на тестовую базу (см. вопрос о тестах ниже).
Образ python:3.12-slim не содержит компилятора, поэтому для mysqlclient в Dockerfile нужны пакеты сборки:
FROM python:3.12-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends default-libmysqlclient-dev build-essential pkg-config \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
Как уменьшить такой образ многоэтапной сборкой и подготовить его к продакшну, разобрано в статье «Django в Docker».
Частые ошибки подключения
Error loading MySQLdb module. Did you install mysqlclient?
Драйвера нет в том окружении, из которого запускается проект. Активируйте venv и выполните pip install mysqlclient. Если используете PyMySQL, проверьте, что pymysql.install_as_MySQLdb() вызывается в settings.py до первого обращения к базе.
Can’t connect to server (2002 или 2003)
Сервер не запущен, слушает другой порт или в HOST указан не тот адрес. Код и текст зависят от драйвера. Так выглядит ошибка mysqlclient на Windows, когда на порту 3306 никто не отвечает:
django.db.utils.OperationalError: (2002, "Can't connect to server on '127.0.0.1' (10061)")
PyMySQL в той же ситуации пишет:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([WinError 10061] No connection could be made because the target machine actively refused it)")
Проверьте службу: sudo systemctl status mysql на Linux, оснастку «Службы» на Windows, docker ps для контейнера. Вариант Can't connect to local MySQL server through socket означает подключение через сокет — разобрано в разделе о localhost выше.
Access denied for user ‘mysite’@‘localhost’ (1045)
Неверный пароль, или пользователь создан для другого хоста. Пользователь 'mysite'@'localhost' не подойдёт для подключения из Docker или с другой машины. Посмотрите, какие пары существуют: SELECT user, host FROM mysql.user;, — и при необходимости создайте пользователя для '%'.
Unknown database ‘mysite’ (1049)
Базу не создали или опечатались в NAME. Список баз показывает SHOW DATABASES;.
Incorrect string value for column (1366)
Полностью ошибка выглядит как Incorrect string value: '\xF0\x9F...' for column: в таблицу пытаются записать эмодзи или другой четырёхбайтовый символ, а таблица создана в utf8mb3. Так бывает со старыми базами. Сконвертируйте базу и таблицы:
ALTER DATABASE mysite CHARACTER SET utf8mb4;
ALTER TABLE blog_post CONVERT TO CHARACTER SET utf8mb4;
ALTER DATABASE меняет кодировку только для новых таблиц, поэтому команду ALTER TABLE нужно выполнить для каждой существующей.
MySQL server has gone away (2006)
Сервер закрыл соединение, простоявшее дольше wait_timeout (по умолчанию 8 часов), а Django попытался его использовать. Чаще всего это происходит в долгих процессах: воркерах Celery, командах управления, скриптах. Установите CONN_MAX_AGE меньше wait_timeout и включите CONN_HEALTH_CHECKS. В собственных циклах вне запросов вызывайте django.db.close_old_connections() перед обращением к базе.
Частые вопросы
Что выбрать для Django: MySQL или PostgreSQL?
Для нового проекта без ограничений чаще выбирают PostgreSQL. Он выполняет миграции в транзакциях, а Django поддерживает его возможности: ArrayField, полнотекстовый поиск, пул соединений. MySQL оправдан, когда его даёт хостинг, его знает команда или к нему уже подключены другие системы. Настройка PostgreSQL описана в статье «Как подключить PostgreSQL к Django».
Почему тесты падают с Access denied к базе test_mysite?
python manage.py test создаёт отдельную базу с префиксом test_ и удаляет её после прогона. Пользователю нужны права и на неё:
GRANT ALL PRIVILEGES ON `test_mysite`.* TO 'mysite'@'localhost';
Без этого появится Got an error creating the test database: (1044, "Access denied for user ..."). В Docker положите эту команду в SQL-файл в /docker-entrypoint-initdb.d, указав хост '%'.
Как подключить Django к существующей базе MySQL?
Укажите базу в DATABASES и сгенерируйте модели по готовым таблицам командой inspectdb:
python manage.py inspectdb > legacy_models.py
В PowerShell 5.1 используйте python manage.py inspectdb | Out-File -Encoding utf8 legacy_models.py, чтобы файл не сохранился в UTF-16. Сгенерированные модели получают managed = False: Django не будет менять эти таблицы миграциями. Если в старой базе есть столбцы типа TIMESTAMP, установите USE_TZ = False, иначе MySQL и Django оба будут переводить время между поясами, и значения исказятся.
Как сделать резервную копию базы MySQL?
Утилитой mysqldump. Флаг --single-transaction снимает согласованную копию таблиц InnoDB без блокировки:
mysqldump --single-transaction -u mysite -p mysite --result-file=mysite.sql
mysql -u mysite -p mysite < mysite.sql
--result-file вместо > защищает от UTF-16 в PowerShell. Там же не работает перенаправление <, поэтому восстанавливайте копию командой mysql -u mysite -p mysite -e "source mysite.sql".
Нужен ли пакет django-mysql?
Для подключения — нет, всё нужное есть в Django. django-mysql добавляет возможности, специфичные для MySQL и MariaDB: поля для списков и множеств в одной строке, подсказки оптимизатору, быстрый приблизительный подсчёт строк, бэкенд кеша на MySQL, именованные блокировки. Перед установкой сверьтесь с поддерживаемыми версиями: на момент публикации PyPI указывает совместимость до Django 6.0 включительно.
Итог
Для подключения MySQL к Django нужны сервер подходящей версии (для Django 6.1 — MySQL 8.4+ или MariaDB 10.11+), база в utf8mb4 с отдельным пользователем, драйвер mysqlclient (или PyMySQL, если сборка невозможна) и DATABASES с ENGINE: django.db.backends.mysql. Включите строгий режим sql_mode и с самого начала учитывайте особенности MySQL: регистронезависимое сравнение строк, миграции без отката и лимит длины индексов. Дальше переходите к запросам в шпаргалке по Django ORM.
- #Django
- #MySQL
- #MariaDB
- #mysqlclient
- #Базы данных