Базы данных
Django официально поддерживает следующие базы данных:
Также существует ряд бэкэндов баз данных, предоставляемых сторонними разработчиками.
Django стремится поддерживать как можно больше функций на всех бэкэндах баз данных. Однако не все бэкэнды баз данных одинаковы, и нам пришлось принять проектные решения о том, какие функции поддерживать и какие предположения можно сделать безопасно.
В этом файле описываются некоторые функции, которые могут быть актуальны для использования Django. Он не предназначен для замены документации или справочных руководств для конкретных серверов.
Общие заметки
Персистентные подключения
Персистентные подключения избегают накладных расходов на повторное установление соединения с базой данных в каждом запросе HTTP. Они управляются параметром CONN_MAX_AGE, который определяет максимальную продолжительность жизни соединения. Его можно задавать независимо для каждой базы данных.
Значение по умолчанию — 0, сохраняя историческое поведение закрытия соединения с базой данных в конце каждого запроса. Чтобы включить персистентные подключения, установите значение CONN_MAX_AGE на положительное целое число в секундах. Для неограниченных персистентных подключений установите его в значение None.
Управление соединениями
Django открывает соединение с базой данных, когда впервые выполняется запрос к базе данных. Это соединение остается открытым и повторно используется в последующих запросах. Django закрывает соединение после превышения максимального возраста, определенного параметром CONN_MAX_AGE, или когда оно больше не может использоваться.
Более подробно, Django автоматически открывает соединение с базой данных всякий раз, когда ему необходимо и его нет — либо потому, что это первое соединение, либо потому, что предыдущее соединение было закрыто.
В начале каждого запроса Django закрывает соединение, если оно достигло максимального возраста. Если ваша база данных закрывает неактивные соединения после некоторого времени, вы должны установить CONN_MAX_AGE на меньшее значение, чтобы Django не пытался использовать соединение, которое было закрыто сервером базы данных. (Эта проблема может затрагивать только сайты с очень низким трафиком.)
В конце каждого запроса Django закрывает соединение, если оно достигло максимального возраста или находится в состоянии необратимой ошибки. Если во время обработки запросов произошли какие-либо ошибки базы данных, Django проверяет, работает ли соединение, и закрывает его, если нет. Таким образом, ошибки базы данных влияют, как максимум, на один запрос на каждый поток обработки приложения; если соединение становится непригодным для использования, следующий запрос получает новое соединение.
Установка CONN_HEALTH_CHECKS в значение True может улучшить надёжность повторного использования соединения и предотвратить ошибки, когда соединение было закрыто сервером базы данных, который теперь готов принимать и обслуживать новые соединения, например, после перезапуска сервера базы данных. Проверка состояния выполняется только один раз за запрос и только если к базе данных обращаются во время обработки запроса.
Ограничения
Поскольку каждый поток сохраняет своё собственное соединение, ваша база данных должна поддерживать по крайней мере столько же одновременных соединений, сколько у вас есть потоков обработки.
Иногда к базе данных не обращаются большинством ваших представлений, например, потому что это база данных внешней системы или благодаря кэшированию. В таких случаях вы должны установить CONN_MAX_AGE на низкое значение или даже на 0, так как поддерживать соединение, которое вряд ли будет повторно использовано, бессмысленно. Это поможет сохранить небольшое количество одновременных соединений с этой базой данных.
Сервер разработки создает новый поток для каждого обрабатываемого запроса, что нейтрализует эффект персистентных подключений. Не включайте их во время разработки.
Когда Django устанавливает соединение с базой данных, он настраивает соответствующие параметры в зависимости от используемого бэкэнда. Если вы включите персистентные соединения, эта настройка больше не повторяется с каждым запросом. Если вы изменяете параметры, такие как уровень изоляции или часовой пояс соединения, вам нужно либо восстановить значения по умолчанию Django в конце каждого запроса, либо принудительно установить соответствующее значение в начале каждого запроса, либо отключить персистентные соединения.
Если соединение создано в длительном процессе за пределами цикла запросов-ответов Django, соединение останется открытым до явного закрытия или истечения срока действия таймаута.
Кодировка
Django предполагает, что все базы данных используют кодировку UTF-8. Использование других кодировок может привести к неожиданному поведению, такому как ошибки «значение слишком длинное» от вашей базы данных для данных, которые валидны в Django. См. заметки по конкретным базам данных ниже для получения информации о правильной настройке вашей базы данных.
Примечания к PostgreSQL
Django поддерживает PostgreSQL 12 и выше. Требуется psycopg 3.1.8+ или psycopg2 2.8.4+, хотя рекомендуется последняя версия psycopg 3.1.8+.
Примечание
Поддержка psycopg2, вероятно, будет устаревшей и удалённой в какой-то момент в будущем.
Была добавлена поддержка psycopg 3.1.8+.
Настройки подключения к PostgreSQL
См. HOST для получения подробностей.
Для подключения с использованием имени службы из файла службы подключения connection service file и пароля из файла паролей password file необходимо указать их в части OPTIONS вашей конфигурации базы данных в DATABASES:
settings.pyDATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"OPTIONS": {
"service": "my_service",
"passfile": ".my_pgpass",
},
}
}
.pg_service.conf[my_service] host=localhost user=USER dbname=NAME port=5432
.my_pgpasslocalhost:5432:NAME:USER:PASSWORD
Бэкэнд PostgreSQL передает содержимое OPTIONS в качестве аргументов ключевых слов конструктору соединения, что позволяет более точно контролировать поведение драйвера. Все доступные параметры подробно описаны в документации PostgreSQL.
Предупреждение
Использование имени службы для целей тестирования не поддерживается. Это может быть реализовано позже.
Оптимизация конфигурации PostgreSQL
Django нуждается в следующих параметрах для своих подключений к базе данных:
-
client_encoding:'UTF8', -
default_transaction_isolation:'read committed'по умолчанию или значение, заданное в параметрах подключения (см. ниже),
Если эти параметры уже имеют правильные значения, Django не будет устанавливать их для каждого нового подключения, что немного улучшает производительность. Вы можете настроить их напрямую в postgresql.conf или более удобно для каждого пользователя базы данных с помощью ALTER ROLE.
Django будет работать нормально без этой оптимизации, но каждое новое соединение выполнит дополнительные запросы для установки этих параметров.
Уровень изоляции базы данных
Подобно самому PostgreSQL, Django по умолчанию использует уровень изоляции READ COMMITTED isolation level. Если вам нужен более высокий уровень изоляции, такой как REPEATABLE READ или SERIALIZABLE, установите его в части OPTIONS вашей конфигурации базы данных в DATABASES:
from django.db.backends.postgresql.psycopg_any import IsolationLevel
DATABASES = {
# ...
"OPTIONS": {
"isolation_level": IsolationLevel.SERIALIZABLE,
},
}
Примечание
При более высоких уровнях изоляции ваше приложение должно быть готовым к обработке исключений, возникающих при ошибках сериализации. Этот параметр предназначен для продвинутого использования.
IsolationLevel был добавлен.
Роль базы данных
Если вам нужно использовать другую роль для подключений к базе данных, отличную от той, которая используется для установления подключения, укажите её в части OPTIONS вашей конфигурации базы данных в DATABASES:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"assume_role": "my_application_role",
},
},
}
Связывание параметров на стороне сервера
С psycopg 3.1.8+ Django по умолчанию использует маркеры-курсоры на стороне клиента. Если вы хотите использовать маркеры-курсоры на стороне сервера, укажите это в части OPTIONS вашей конфигурации базы данных в DATABASES:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"server_side_binding": True,
},
},
}
Этот параметр игнорируется при использовании psycopg2.
Индексы для столбцов varchar и text
При указании db_index=True для полей вашей модели Django обычно генерирует одно CREATE INDEX утверждение. Однако, если тип базы данных для поля — varchar или text (например, используемый CharField, FileField, и TextField), Django создаст дополнительный индекс, использующий соответствующий PostgreSQL операторный класс для столбца. Дополнительный индекс необходим для правильного выполнения запросов, использующих LIKE оператор в своём SQL, как это делается с contains и startswith типами поиска.
Операция миграции для добавления расширений
Если вам нужно добавить PostgreSQL расширение (например, hstore, postgis, и т.д.) с помощью миграции, используйте операцию CreateExtension.
Курсоры на стороне сервера
При использовании QuerySet.iterator(), Django открывает курсор на стороне сервера. По умолчанию PostgreSQL предполагает, что будет извлечено только первые 10% результатов запросов к курсору. Планировщик запросов тратит меньше времени на планирование запроса и начинает быстрее возвращать результаты, но это может снизить производительность, если извлекается более 10% результатов. Предположения PostgreSQL о количестве строк, извлекаемых для запроса курсора, контролируются параметром cursor_tuple_fraction.
Пулы транзакций и курсоры на стороне сервера
Использование пула соединений в режиме пула транзакций (например, PgBouncer) требует отключения курсоров на стороне сервера для этого подключения.
Курсоры на стороне сервера локальны для подключения и остаются открытыми в конце транзакции, когда AUTOCOMMIT равен True. Последующая транзакция может попытаться извлечь дополнительные результаты из курсора на стороне сервера. В режиме пула транзакций нет гарантии, что последующие транзакции будут использовать то же самое соединение. Если используется другое соединение, возникает ошибка, когда транзакция ссылается на курсор на стороне сервера, поскольку курсоры на стороне сервера доступны только в соединении, в котором они были созданы.
Одним из решений является отключение курсоров на стороне сервера для подключения в DATABASES путём установки DISABLE_SERVER_SIDE_CURSORS в True.
Для использования курсоров на стороне сервера в режиме пула транзакций можно настроить другое подключение к базе данных для выполнения запросов, использующих курсоры на стороне сервера. Это подключение должно быть либо напрямую к базе данных, либо к пулу соединений в режиме сессионного пула.
Другой вариант — обернуть каждый QuerySet с курсорами на стороне сервера в блок atomic(), так как он отключает autocommit на время транзакции. Таким образом, курсор на стороне сервера будет существовать только на время транзакции.
Указание значений автоинкрементируемых первичных ключей вручную
Django использует идентификационные столбцы PostgreSQL для хранения автоинкрементируемых первичных ключей. Идентификационный столбец заполняется значениями из последовательности, которая отслеживает следующее доступное значение. Ручное присвоение значения полю с автоинкрементом не обновляет последовательность поля, что может впоследствии привести к конфликту. Например:
>>> from django.contrib.auth.models import User >>> User.objects.create(username="alice", pk=1) <User: alice> >>> # The sequence hasn't been updated; its next value is 1. >>> User.objects.create(username="bob") IntegrityError: duplicate key value violates unique constraint "auth_user_pkey" DETAIL: Key (id)=(1) already exists.
Если вам нужно указать такие значения, сбросьте последовательность после этого, чтобы избежать повторного использования значения, которое уже есть в таблице. Команда управления sqlsequencereset генерирует SQL-запросы для этого.
Шаблоны тестовых баз данных
Можно использовать настройку TEST['TEMPLATE'] для указания шаблона (например, 'template0') для создания тестовой базы данных.
Ускорение выполнения тестов с помощью настроек, не требующих сохранения
Вы можете ускорить время выполнения тестов, настроив PostgreSQL для работы без сохранения изменений.
Предупреждение
Это опасно: это сделает вашу базу данных более уязвимой к потере данных или повреждению в случае сбоя сервера или отключения питания. Используйте это только на тестовых машинах, где вы легко можете восстановить всё содержимое всех баз данных в кластере.
Примечания по MariaDB
Django поддерживает MariaDB 10.4 и выше.
Для использования MariaDB используйте бэкэнд MySQL, который используется обоими. См. Примечания по MySQL для получения более подробной информации.
Примечания по MySQL
Поддержка версий
Django поддерживает MySQL 8.0.11 и выше.
Функция inspectdb Django использует базу данных information_schema, которая содержит подробные данные обо всех схемах баз данных.
Django ожидает, что база данных будет поддерживать Unicode (кодировку UTF-8) и делегирует ей задачу обеспечения транзакций и целостности ссылок. Важно понимать, что оба последних не на самом деле выполняются MySQL при использовании движка хранения MyISAM, см. следующий раздел.
Движки хранения
MySQL имеет несколько движков хранения. Вы можете изменить движок хранения по умолчанию в конфигурации сервера.
По умолчанию в MySQL используется движок хранения InnoDB. Этот движок полностью транзакционный и поддерживает внешние ключи. Это рекомендуемый выбор. Однако счетчик автоинкремента InnoDB теряется при перезапуске MySQL, потому что он не запоминает значение AUTO_INCREMENT, а вместо этого пересоздаёт его как “max(id)+1”. Это может привести к непреднамеренному повторному использованию значений AutoField.
Основные недостатки движка MyISAM заключаются в том, что он не поддерживает транзакции или проверку ограничений внешних ключей.
Драйверы MySQL DB API
MySQL имеет несколько драйверов, которые реализуют описанный в PEP 249 Python Database API:
- mysqlclient — это родной драйвер. Это рекомендуемый вариант.
- MySQL Connector/Python — это чисто Python-драйвер от Oracle, который не требует библиотеки MySQL client или каких-либо Python-модулей за пределами стандартной библиотеки.
Эти драйверы потокобезопасны и предоставляют пулы соединений.
В дополнение к драйверу DB API Django нуждается в адаптере для доступа к драйверам баз данных из его ORM. Django предоставляет адаптер для mysqlclient, в то время как MySQL Connector/Python включает собственный.
mysqlclient
Django требует mysqlclient 1.4.3 или более поздней версии.
MySQL Connector/Python
MySQL Connector/Python доступен на странице загрузки. Адаптер Django доступен в версиях 1.1.X и более поздних. Он может не поддерживать самые свежие версии Django.
Определения часовых поясов
Если вы планируете использовать поддержку часовых поясов Django, используйте mysql_tzinfo_to_sql для загрузки таблиц часовых поясов в базу данных MySQL. Это необходимо сделать один раз для вашего сервера MySQL, а не для каждой базы данных.
Создание вашей базы данных
Вы можете создать свою базу данных с помощью командной строки и этого SQL:
CREATE DATABASE <dbname> CHARACTER SET utf8;
Это гарантирует, что все таблицы и столбцы по умолчанию будут использовать UTF-8.
Настройки сопоставления
Настройка сопоставления для столбца управляет порядком сортировки данных, а также тем, какие строки сравниваются как равные. Вы можете указать параметр db_collation для установки имени сопоставления столбца для CharField и TextField.
Сопоставление также может быть установлено на уровне базы данных и на уровне таблицы. Это подробно описано в документации MySQL. В таких случаях вы должны установить сопоставление, непосредственно манипулируя настройками базы данных или таблицами. Django не предоставляет API для их изменения.
По умолчанию, с базой данных UTF-8, MySQL будет использовать сопоставление utf8_general_ci. Это приводит к тому, что все сравнения строк на равенство выполняются в режиме без учета регистра. То есть, "Fred" и "freD" считаются равными на уровне базы данных. Если у вас есть уникальное ограничение на поле, попытка вставки "aa" и "AA" в один и тот же столбец будет незаконной, так как они сравниваются как равные (и, следовательно, не уникальные) с сопоставлением по умолчанию. Если вы хотите сравнения с учетом регистра для конкретного столбца или таблицы, измените столбец или таблицу, чтобы использовать сопоставление utf8_bin.
Обратите внимание, что, согласно наборам символов MySQL Unicode, сравнения для сопоставления utf8_general_ci быстрее, но немного менее корректны, чем сравнения для utf8_unicode_ci. Если это приемлемо для вашего приложения, вы должны использовать utf8_general_ci, поскольку оно быстрее. Если это неприемлемо (например, если вам требуется порядок немецкого словаря), используйте utf8_unicode_ci, поскольку оно более точно.
Предупреждение
Формы-наборы моделей проверяют уникальные поля в режиме с учетом регистра. Таким образом, при использовании сопоставления без учета регистра набор форм с уникальными значениями поля, отличающимися только регистром, пройдет проверку, но при вызове save(), будет поднято IntegrityError.
Подключение к базе данных
Обратитесь к документации по настройкам.
Настройки подключения используются в таком порядке:
Другими словами, если вы установили имя базы данных в OPTIONS, это будет иметь приоритет над NAME, что переопределит любые значения в файле опций MySQL.
Вот пример конфигурации, которая использует файл опций MySQL:
# settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"OPTIONS": {
"read_default_file": "/path/to/my.cnf",
},
}
}
# my.cnf [client] database = NAME user = USER password = PASSWORD default-character-set = utf8
Некоторые другие опции подключения MySQLdb могут быть полезны, такие как ssl, init_command, и sql_mode.
Установка sql_mode
Значение параметра sql_mode по умолчанию содержит STRICT_TRANS_TABLES. Эта опция преобразует предупреждения в ошибки, когда данные усекаются при вставке, поэтому Django настоятельно рекомендует активировать строгий режим для MySQL, чтобы предотвратить потерю данных (либо STRICT_TRANS_TABLES или STRICT_ALL_TABLES).
Если вам нужно настроить режим SQL, вы можете установить переменную sql_mode, как и другие опции MySQL: либо в файле конфигурации, либо с помощью записи 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" в части OPTIONS вашей конфигурации базы данных в DATABASES.
Уровень изоляции
При запуске одновременных нагрузок транзакции базы данных из разных сессий (скажем, отдельных потоков, обрабатывающих разные запросы) могут взаимодействовать друг с другом. Эти взаимодействия зависят от уровня изоляции транзакций каждой сессии. Уровень изоляции транзакций. Вы можете установить уровень изоляции соединения с помощью записи 'isolation_level' в части OPTIONS вашей конфигурации базы данных в DATABASES. Допустимые значения для этой записи — четыре стандартных уровня изоляции:
'read uncommitted''read committed''repeatable read''serializable'
или None, чтобы использовать уровень изоляции, настроенный на сервере. Однако Django лучше всего работает с и по умолчанию использует «read committed», а не с «repeatable read», которое является значением по умолчанию в MySQL. Возможна потеря данных при использовании «repeatable read». В частности, вы можете наблюдать случаи, когда get_or_create() вызовет IntegrityError, но объект не появится в последующем вызове get().
Создание ваших таблиц
Когда Django генерирует схему, он не указывает движок хранения, поэтому таблицы будут созданы с тем движком хранения, который настроен по умолчанию на вашем сервере базы данных.
Самое простое решение — установить на вашем сервере базы данных желаемый движок хранения по умолчанию.
-
После создания таблиц выполните оператор
ALTER TABLEдля преобразования таблицы в новый движок хранения (например, InnoDB):ALTER TABLE <tablename> ENGINE=INNODB;
Это может быть утомительно, если у вас много таблиц.
-
Еще один вариант — использовать опцию
init_commandдля MySQLdb перед созданием таблиц:"OPTIONS": { "init_command": "SET default_storage_engine=INNODB", }Это устанавливает движок хранения по умолчанию при подключении к базе данных. После создания таблиц вы должны удалить эту опцию, так как она добавляет запрос, необходимый только при создании таблиц, к каждому подключению к базе данных.
Имена таблиц
Существуют известные проблемы даже в последних версиях MySQL, которые могут привести к изменению регистра имени таблицы при выполнении определенных SQL-запросов в определенных условиях. Рекомендуется использовать имена таблиц строчными буквами, если это возможно, чтобы избежать возможных проблем, которые могут возникнуть из-за этого поведения. Django использует имена таблиц строчными буквами при автоматическом создании имён таблиц из моделей, поэтому это преимущественно нужно учитывать, если вы переопределяете имя таблицы с помощью параметра db_table.
Сохраняемые точки
Как Django ORM, так и MySQL (при использовании движка хранения InnoDB движок хранения) поддерживают сохраняемые точки базы данных.
Если вы используете движок хранения MyISAM, будьте готовы к тому, что вы получите ошибки, сгенерированные базой данных, если попытаетесь использовать методы API для работы с сохраняемыми точками. Причина в том, что обнаружение движка хранения базы данных MySQL/таблицы — ресурсоемкая операция, поэтому было решено, что не стоит динамически преобразовывать эти методы в no-op в зависимости от результатов такого обнаружения.
Примечания к определённым полям
Поля символьного типа
Любые поля, которые хранятся с типами столбцов VARCHAR, могут иметь их max_length ограничены 255 символами, если вы используете unique=True для поля. Это влияет на CharField, SlugField. См. документацию MySQL для получения дополнительной информации.
TextField ограничения
MySQL может индексировать только первые N символов столбца BLOB или TEXT. Поскольку TextField не имеет определенной длины, вы не можете пометить его как unique=True. MySQL сообщит: «Столбец BLOB/TEXT ‘<db_column>’ используется в спецификации ключа без длины ключа».
Поддержка дробных секунд для полей Time и DateTime
MySQL может хранить дробные секунды при условии, что в определении столбца указано дробное представление (например, DATETIME(6)).
Django не будет обновлять существующие столбцы, чтобы включить дробные секунды, если сервер базы данных их поддерживает. Если вы хотите включить их в существующей базе данных, вам необходимо вручную обновить столбец в целевой базе данных, выполнив команду, подобную:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
или используя операцию RunSQL в миграции данных.
TIMESTAMP столбцы
Если вы используете базу данных устаревшего типа, содержащую TIMESTAMP столбцы, необходимо установить USE_TZ = False, чтобы избежать повреждения данных. inspectdb отображает эти столбцы на DateTimeField, и если вы включите поддержку часовых поясов, как MySQL, так и Django попытаются преобразовать значения из UTC в локальное время.
Блокировка строк с QuerySet.select_for_update()
MySQL и MariaDB не поддерживают некоторые параметры оператора SELECT ... FOR UPDATE. Если select_for_update() используется с неподдерживаемым параметром, то возбуждается NotSupportedError.
| Параметр | MariaDB | MySQL |
|---|---|---|
SKIP LOCKED | X (≥10.6) | X |
NOWAIT | X | X |
OF | X | |
NO KEY |
При использовании select_for_update() в MySQL убедитесь, что вы фильтруете набор запросов по набору полей, содержащихся в уникальных ограничениях, или только по полям, охватываемым индексами. В противном случае эксклюзивный блокировка записи будет приобретена для всей таблицы на все время транзакции.
Автоматическое приведение типов может привести к непредсказуемым результатам
При выполнении запроса к строковому типу, но с целочисленным значением, MySQL приведет типы всех значений в таблице к целочисленному типу перед выполнением сравнения. Если ваша таблица содержит значения 'abc', 'def', и вы выполняете запрос на WHERE mycolumn=0, обе строки будут соответствовать. Аналогично, WHERE mycolumn=1 будет соответствовать значению 'abc1'. Поэтому поля строкового типа, включенные в Django, всегда преобразуют значение в строку перед использованием в запросе.
Если вы реализуете пользовательские поля модели, наследующиеся от Field непосредственно, переопределяете get_prep_value() или используете RawSQL, extra() или raw(), вам следует убедиться, что вы выполнили соответствующее приведение типов.
Заметки по SQLite
Django поддерживает SQLite 3.27.0 и более поздние версии.
SQLite предоставляет отличную альтернативу для разработки приложений, которые в основном предназначены для чтения или требуют меньшего объема установки. Однако, как и во всех серверах баз данных, есть некоторые отличия, специфичные для SQLite, о которых вам следует знать.
Сопоставление подстрок и регистрозависимость
Во всех версиях SQLite наблюдается несколько неинтуитивное поведение при попытке сопоставления некоторых типов строк. Это происходит при использовании фильтров iexact или contains в наборах запросов. Поведение делится на два случая:
1. При сопоставлении подстрок все соответствия производятся без учета регистра. Например, фильтр filter(name__contains="aa") будет соответствовать имени "Aabb".
2. Для строк, содержащих символы за пределами ASCII-диапазона, все точные соответствия строк выполняются с учетом регистра, даже когда в запрос передаются параметры без учета регистра. Таким образом, фильтр iexact будет вести себя точно так же, как фильтр exact в этих случаях.
Возможные обходные пути описаны на sqlite.org, но они не используются в стандартном SQLite-бекенде Django, поскольку их внедрение было бы достаточно сложным. Поэтому Django предоставляет стандартное поведение SQLite, и вам следует об этом помнить при выполнении фильтрации без учета регистра или фильтрации по подстрокам.
Обработка десятичных чисел
В SQLite нет реального внутреннего типа decimal. Десятичные значения преобразуются во внутренний тип REAL (8-байтовое число с плавающей точкой IEEE), как описано в документации по типам данных SQLite https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes, поэтому они не поддерживают правильно округленные операции с десятичной плавающей точкой.
“Ошибка базы данных заблокирована”
SQLite предназначен для легких баз данных и поэтому не может поддерживать высокий уровень параллелизма. Ошибки OperationalError: database is locked указывают на то, что ваше приложение использует больше параллельности, чем sqlite может обработать в стандартной конфигурации. Эта ошибка означает, что один поток или процесс имеет эксклюзивную блокировку подключения к базе данных, а другой поток истек, ожидая освобождения блокировки.
В Python-оболочке SQLite есть значение таймаута по умолчанию, которое определяет, как долго второй поток может ожидать блокировки, прежде чем он истечет и возбудит ошибку OperationalError: database
is locked.
Если вы получаете эту ошибку, вы можете решить ее:
- Переключиться на другой бэкенд базы данных. В какой-то момент SQLite становится слишком «легким» для реальных приложений, и подобные ошибки параллелизма показывают, что вы достигли этой точки.
- Переписать свой код, чтобы уменьшить параллелизм и гарантировать, что транзакции базы данных будут кратковременными.
-
Увеличить значение таймаута по умолчанию, задав параметр базы данных
timeout:"OPTIONS": { # ... "timeout": 20, # ... }Это заставит SQLite подождать немного дольше, прежде чем выбросить ошибки «база данных заблокирована»; это не решит их по-настоящему.
QuerySet.select_for_update() не поддерживается
SQLite не поддерживает синтаксис SELECT ... FOR UPDATE. Вызов не окажет никакого влияния.
Изоляция при использовании QuerySet.iterator()
Существуют специальные соображения, описанные в Изоляции в SQLite, когда вы изменяете таблицу во время итерации по ней с использованием QuerySet.iterator(). Если строка добавляется, изменяется или удаляется внутри цикла, эта строка может или не может появиться или может появиться дважды в последующих результатах, полученных из итератора. Ваш код должен обработать это.
Включение расширения JSON1 в SQLite
Чтобы использовать JSONField в SQLite, необходимо включить расширение JSON1 в библиотеке Python sqlite3. Если расширение не включено в вашей установке, будет возбуждено системное исключение (fields.E180).
Чтобы включить расширение JSON1, вы можете следовать инструкциям на странице вики.
Примечание
Расширение JSON1 включено по умолчанию в SQLite 3.38+.
Заметки по Oracle
Django поддерживает Oracle Database Server версии 19c и выше. Требуется версия 1.3.2 или выше драйвера Python oracledb.
Устаревшая с версии 5.0: Поддержка cx_Oracle устарела.
Для работы команды python manage.py migrate ваш пользователь Oracle базы данных должен иметь права на выполнение следующих команд:
- CREATE TABLE
- CREATE SEQUENCE
- CREATE PROCEDURE
- CREATE TRIGGER
Для запуска набора тестов проекта пользователю обычно требуется дополнительные права:
- СОЗДАТЬ ПОЛЬЗОВАТЕЛЯ
- ИЗМЕНИТЬ ПОЛЬЗОВАТЕЛЯ
- УДАЛИТЬ ПОЛЬЗОВАТЕЛЯ
- СОЗДАТЬ БАЗУ ДАННЫХ
- УДАЛИТЬ БАЗУ ДАННЫХ
- СОЗДАТЬ СЕССИЮ С ПРАВОМ АДМИНИСТРАТОРА
- СОЗДАТЬ ТАБЛИЦУ С ПРАВОМ АДМИНИСТРАТОРА
- СОЗДАТЬ ПОСЛЕДОВАТЕЛЬНОСТЬ С ПРАВОМ АДМИНИСТРАТОРА
- СОЗДАТЬ ПРОЦЕДУРУ С ПРАВОМ АДМИНИСТРАТОРА
- СОЗДАТЬ ТРИГГЕР С ПРАВОМ АДМИНИСТРАТОРА
Пока у роли RESOURCE есть необходимые CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, и CREATE TRIGGER привилегии, и пользователь, которому предоставлено RESOURCE WITH ADMIN OPTION, может предоставить RESOURCE, такой пользователь не может предоставить отдельные привилегии (например, CREATE TABLE), и поэтому RESOURCE WITH ADMIN OPTION обычно недостаточно для запуска тестов.
Некоторые наборы тестов также создают представления или материализованные представления; для их запуска пользователю также нужны CREATE VIEW WITH ADMIN OPTION и CREATE MATERIALIZED VIEW WITH ADMIN OPTION привилегии. В частности, это необходимо для собственного набора тестов Django.
Все эти привилегии включены в роль DBA, что подходит для использования на базе данных частного разработчика.
Бэкенд базы данных Oracle использует пакеты SYS.DBMS_LOB и SYS.DBMS_RANDOM, поэтому вашему пользователю потребуются права выполнения на них. Обычно он доступен всем пользователям по умолчанию, но если это не так, вам нужно предоставить разрешения следующим образом:
GRANT EXECUTE ON SYS.DBMS_LOB TO user; GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
Подключение к базе данных
Чтобы подключиться, используя имя службы вашей базы данных Oracle, ваш файл settings.py должен выглядеть примерно так:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
"NAME": "xe",
"USER": "a_user",
"PASSWORD": "a_password",
"HOST": "",
"PORT": "",
}
}
В этом случае вы должны оставить оба HOST и PORT пустыми. Однако, если вы не используете файл tnsnames.ora или аналогичный метод именования и хотите подключиться, используя SID («xe» в этом примере), то заполните оба HOST и PORT следующим образом:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
"NAME": "xe",
"USER": "a_user",
"PASSWORD": "a_password",
"HOST": "dbprod01ned.mycompany.com",
"PORT": "1540",
}
}
Вы должны либо указать и HOST, и PORT, либо оставить оба пустыми. Django будет использовать другой дескриптор подключения в зависимости от этого выбора.
Полный DSN и Easy Connect
Строка Full DSN или Easy Connect может быть использована в NAME, если оба HOST и PORT пусты. Этот формат требуется при использовании RAC или подключаемых баз данных без tnsnames.ora, например.
Пример строки Easy Connect:
"NAME": "localhost:1521/orclpdb1"
Пример строки Full DSN:
"NAME": (
"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
"(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
)
Многопоточный вариант
Если вы планируете запустить Django в многопоточной среде (например, Apache с использованием модуля MPM по умолчанию на любой современной операционной системе), то вы обязательно должны установить параметр threaded вашей конфигурации базы данных Oracle на True:
"OPTIONS": {
"threaded": True,
}
Невыполнение этого может привести к сбоям и другому странному поведению.
INSERT … RETURNING INTO
По умолчанию бэкенд Oracle использует предложение RETURNING INTO, чтобы эффективно получить значение AutoField при вставке новых строк. Это поведение может привести к DatabaseError в некоторых необычных ситуациях, таких как вставка в удаленную таблицу или в представление с триггером INSTEAD OF. Предложение RETURNING INTO можно отключить, установив параметр use_returning_into конфигурации базы данных на False:
"OPTIONS": {
"use_returning_into": False,
}
В этом случае бэкенд Oracle будет использовать отдельный запрос SELECT для получения значений AutoField.
Проблемы с именами
Oracle накладывает ограничение на длину имени в 30 символов. Чтобы учесть это, бэкенд обрезает идентификаторы базы данных до нужного размера, заменяя последние четыре символа усеченного имени повторяющимся значением MD5. Кроме того, бэкенд преобразует идентификаторы базы данных в верхний регистр.
Чтобы предотвратить эти преобразования (это обычно требуется только при работе со старыми базами данных или доступе к таблицам, принадлежащим другим пользователям), используйте имя в кавычках в качестве значения для db_table:
class LegacyModel(models.Model):
class Meta:
db_table = '"name_left_in_lowercase"'
class ForeignModel(models.Model):
class Meta:
db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
Имена в кавычках также можно использовать с другими поддерживаемыми Django базами данных; за исключением Oracle, однако, кавычки не имеют эффекта.
При выполнении migrate, может возникнуть ошибка ORA-06552, если определенные ключевые слова Oracle используются в качестве имени поля модели или значения параметра db_column. Django приводит все идентификаторы, используемые в запросах, к кавычкам, чтобы предотвратить большинство таких проблем, но эта ошибка все же может возникнуть, когда тип данных Oracle используется в качестве имени столбца. В частности, старайтесь избегать использования имен date, timestamp, number или float в качестве имени поля.
NULL и пустые строки
Django обычно предпочитает использовать пустую строку ('') вместо NULL, но Oracle обрабатывает оба идентично. Чтобы обойти это, бэкенд Oracle игнорирует явный параметр null для полей, которые могут иметь пустую строку в качестве значения, и генерирует DDL так, как будто null=True. При извлечении из базы данных предполагается, что значение NULL в одном из этих полей на самом деле означает пустую строку, и данные безмолвно преобразуются, чтобы отразить это предположение.
TextField ограничения
Бэкенд Oracle хранит TextFields в виде столбцов типа NCLOB. Oracle накладывает некоторые ограничения на использование таких столбцов LOB в целом:
- Столбцы LOB не могут использоваться в качестве первичных ключей.
- Столбцы LOB не могут использоваться в индексах.
- Столбцы LOB не могут использоваться в списке
SELECT DISTINCT. Это означает, что попытка использования методаQuerySet.distinctдля модели, которая включает столбцыTextField, приведет к ошибкеORA-00932при запуске на Oracle. В качестве обходного пути используйте методQuerySet.deferв сочетании сdistinct(), чтобы предотвратить включение столбцовTextFieldв списокSELECT DISTINCT.
Наследование встроенных бэкендов баз данных
Django поставляется со встроенными бэкендами баз данных. Вы можете наследоваться от существующих бэкендов баз данных, чтобы изменить их поведение, возможности или конфигурацию.
Например, предположим, что вам нужно изменить одну функцию базы данных. Сначала вам нужно создать новую папку с модулем base в ней. Например:
mysite/
...
mydbengine/
__init__.py
base.py
Модуль base.py должен содержать класс с именем DatabaseWrapper, который наследуется от существующего движка из модуля django.db.backends. Вот пример наследования от движка PostgreSQL для изменения класса функции allows_group_by_selected_pks_on_model:
mysite/mydbengine/base.pyfrom django.db.backends.postgresql import base, features
class DatabaseFeatures(features.DatabaseFeatures):
def allows_group_by_selected_pks_on_model(self, model):
return True
class DatabaseWrapper(base.DatabaseWrapper):
features_class = DatabaseFeatures
Наконец, вы должны указать DATABASE-ENGINE в своем файле settings.py:
DATABASES = {
"default": {
"ENGINE": "mydbengine",
# ...
},
}
Вы можете увидеть текущий список движков баз данных, просмотрев django/db/backends.
Использование бэкенда базы данных стороннего разработчика
Помимо официально поддерживаемых баз данных, существуют бэкенды сторонних разработчиков, которые позволяют использовать другие базы данных с Django:
Версии Django и возможности ORM, поддерживаемые этими неофициальными бэкендами, значительно различаются. Запросы о конкретных возможностях этих неофициальных бэкендов, а также любые запросы поддержки следует направлять в каналы поддержки, предоставляемые каждым проектом стороннего разработчика.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.0/ref/databases/