12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271 |
- =========
- Databases
- =========
- Django officially supports the following databases:
- * :ref:`PostgreSQL <postgresql-notes>`
- * :ref:`MariaDB <mariadb-notes>`
- * :ref:`MySQL <mysql-notes>`
- * :ref:`Oracle <oracle-notes>`
- * :ref:`SQLite <sqlite-notes>`
- There are also a number of :ref:`database backends provided by third parties
- <third-party-notes>`.
- Django attempts to support as many features as possible on all database
- backends. However, not all database backends are alike, and we've had to make
- design decisions on which features to support and which assumptions we can make
- safely.
- This file describes some of the features that might be relevant to Django
- usage. It is not intended as a replacement for server-specific documentation or
- reference manuals.
- General notes
- =============
- .. _persistent-database-connections:
- Persistent connections
- ----------------------
- Persistent connections avoid the overhead of reestablishing a connection to
- the database in each HTTP request. They're controlled by the
- :setting:`CONN_MAX_AGE` parameter which defines the maximum lifetime of a
- connection. It can be set independently for each database.
- The default value is ``0``, preserving the historical behavior of closing the
- database connection at the end of each request. To enable persistent
- connections, set :setting:`CONN_MAX_AGE` to a positive integer of seconds. For
- unlimited persistent connections, set it to ``None``.
- Connection management
- ~~~~~~~~~~~~~~~~~~~~~
- Django opens a connection to the database when it first makes a database
- query. It keeps this connection open and reuses it in subsequent requests.
- Django closes the connection once it exceeds the maximum age defined by
- :setting:`CONN_MAX_AGE` or when it isn't usable any longer.
- In detail, Django automatically opens a connection to the database whenever it
- needs one and doesn't have one already — either because this is the first
- connection, or because the previous connection was closed.
- At the beginning of each request, Django closes the connection if it has
- reached its maximum age. If your database terminates idle connections after
- some time, you should set :setting:`CONN_MAX_AGE` to a lower value, so that
- Django doesn't attempt to use a connection that has been terminated by the
- database server. (This problem may only affect very low traffic sites.)
- At the end of each request, Django closes the connection if it has reached its
- maximum age or if it is in an unrecoverable error state. If any database
- errors have occurred while processing the requests, Django checks whether the
- connection still works, and closes it if it doesn't. Thus, database errors
- affect at most one request per each application's worker thread; if the
- connection becomes unusable, the next request gets a fresh connection.
- Setting :setting:`CONN_HEALTH_CHECKS` to ``True`` can be used to improve the
- robustness of connection reuse and prevent errors when a connection has been
- closed by the database server which is now ready to accept and serve new
- connections, e.g. after database server restart. The health check is performed
- only once per request and only if the database is being accessed during the
- handling of the request.
- Caveats
- ~~~~~~~
- Since each thread maintains its own connection, your database must support at
- least as many simultaneous connections as you have worker threads.
- Sometimes a database won't be accessed by the majority of your views, for
- example because it's the database of an external system, or thanks to caching.
- In such cases, you should set :setting:`CONN_MAX_AGE` to a low value or even
- ``0``, because it doesn't make sense to maintain a connection that's unlikely
- to be reused. This will help keep the number of simultaneous connections to
- this database small.
- The development server creates a new thread for each request it handles,
- negating the effect of persistent connections. Don't enable them during
- development.
- When Django establishes a connection to the database, it sets up appropriate
- parameters, depending on the backend being used. If you enable persistent
- connections, this setup is no longer repeated every request. If you modify
- parameters such as the connection's isolation level or time zone, you should
- either restore Django's defaults at the end of each request, force an
- appropriate value at the beginning of each request, or disable persistent
- connections.
- If a connection is created in a long-running process, outside of Django’s
- request-response cycle, the connection will remain open until explicitly
- closed, or timeout occurs. You can use ``django.db.close_old_connections()`` to
- close all old or unusable connections.
- Encoding
- --------
- Django assumes that all databases use UTF-8 encoding. Using other encodings may
- result in unexpected behavior such as "value too long" errors from your
- database for data that is valid in Django. See the database specific notes
- below for information on how to set up your database correctly.
- .. _postgresql-notes:
- PostgreSQL notes
- ================
- Django supports PostgreSQL 14 and higher. `psycopg`_ 3.1.8+ or `psycopg2`_
- 2.8.4+ is required, though the latest `psycopg`_ 3.1.8+ is recommended.
- .. note::
- Support for ``psycopg2`` is likely to be deprecated and removed at some
- point in the future.
- .. _postgresql-connection-settings:
- PostgreSQL connection settings
- -------------------------------
- See :setting:`HOST` for details.
- To connect using a service name from the `connection service file`_ and a
- password from the `password file`_, you must specify them in the
- :setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`:
- .. code-block:: python
- :caption: ``settings.py``
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.postgresql",
- "OPTIONS": {
- "service": "my_service",
- "passfile": ".my_pgpass",
- },
- }
- }
- .. code-block:: text
- :caption: ``.pg_service.conf``
- [my_service]
- host=localhost
- user=USER
- dbname=NAME
- port=5432
- .. code-block:: text
- :caption: ``.my_pgpass``
- localhost:5432:NAME:USER:PASSWORD
- The PostgreSQL backend passes the content of :setting:`OPTIONS` as keyword
- arguments to the connection constructor, allowing for more advanced control
- of driver behavior. All available `parameters`_ are described in detail in the
- PostgreSQL documentation.
- .. _connection service file: https://www.postgresql.org/docs/current/libpq-pgservice.html
- .. _password file: https://www.postgresql.org/docs/current/libpq-pgpass.html
- .. _parameters: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
- .. warning::
- Using a service name for testing purposes is not supported. This
- :ticket:`may be implemented later <33685>`.
- Optimizing PostgreSQL's configuration
- -------------------------------------
- Django needs the following parameters for its database connections:
- - ``client_encoding``: ``'UTF8'``,
- - ``default_transaction_isolation``: ``'read committed'`` by default,
- or the value set in the connection options (see below),
- - ``timezone``:
- - when :setting:`USE_TZ` is ``True``, ``'UTC'`` by default, or the
- :setting:`TIME_ZONE <DATABASE-TIME_ZONE>` value set for the connection,
- - when :setting:`USE_TZ` is ``False``, the value of the global
- :setting:`TIME_ZONE` setting.
- If these parameters already have the correct values, Django won't set them for
- every new connection, which improves performance slightly. You can configure
- them directly in :file:`postgresql.conf` or more conveniently per database
- user with `ALTER ROLE`_.
- Django will work just fine without this optimization, but each new connection
- will do some additional queries to set these parameters.
- .. _ALTER ROLE: https://www.postgresql.org/docs/current/sql-alterrole.html
- .. _database-isolation-level:
- Isolation level
- ---------------
- Like PostgreSQL itself, Django defaults to the ``READ COMMITTED`` `isolation
- level`_. If you need a higher isolation level such as ``REPEATABLE READ`` or
- ``SERIALIZABLE``, set it in the :setting:`OPTIONS` part of your database
- configuration in :setting:`DATABASES`::
- from django.db.backends.postgresql.psycopg_any import IsolationLevel
- DATABASES = {
- # ...
- "OPTIONS": {
- "isolation_level": IsolationLevel.SERIALIZABLE,
- },
- }
- .. note::
- Under higher isolation levels, your application should be prepared to
- handle exceptions raised on serialization failures. This option is
- designed for advanced uses.
- .. _isolation level: https://www.postgresql.org/docs/current/transaction-iso.html
- .. _database-role:
- Role
- ----
- If you need to use a different role for database connections than the role use
- to establish the connection, set it in the :setting:`OPTIONS` part of your
- database configuration in :setting:`DATABASES`::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.postgresql",
- # ...
- "OPTIONS": {
- "assume_role": "my_application_role",
- },
- },
- }
- .. _postgresql-pool:
- Connection pool
- ---------------
- .. versionadded:: 5.1
- To use a connection pool with `psycopg`_, you can either set ``"pool"`` in the
- :setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`
- to be a dict to be passed to :class:`~psycopg:psycopg_pool.ConnectionPool`, or
- to ``True`` to use the ``ConnectionPool`` defaults::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.postgresql",
- # ...
- "OPTIONS": {
- "pool": True,
- },
- },
- }
- This option requires ``psycopg[pool]`` or :pypi:`psycopg-pool` to be installed
- and is ignored with ``psycopg2``.
- .. _database-server-side-parameters-binding:
- Server-side parameters binding
- ------------------------------
- With `psycopg`_ 3.1.8+, Django defaults to the :ref:`client-side binding
- cursors <psycopg:client-side-binding-cursors>`. If you want to use the
- :ref:`server-side binding <psycopg:server-side-binding>` set it in the
- :setting:`OPTIONS` part of your database configuration in
- :setting:`DATABASES`::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.postgresql",
- # ...
- "OPTIONS": {
- "server_side_binding": True,
- },
- },
- }
- This option is ignored with ``psycopg2``.
- Indexes for ``varchar`` and ``text`` columns
- --------------------------------------------
- When specifying ``db_index=True`` on your model fields, Django typically
- outputs a single ``CREATE INDEX`` statement. However, if the database type
- for the field is either ``varchar`` or ``text`` (e.g., used by ``CharField``,
- ``FileField``, and ``TextField``), then Django will create
- an additional index that uses an appropriate `PostgreSQL operator class`_
- for the column. The extra index is necessary to correctly perform
- lookups that use the ``LIKE`` operator in their SQL, as is done with the
- ``contains`` and ``startswith`` lookup types.
- .. _PostgreSQL operator class: https://www.postgresql.org/docs/current/indexes-opclass.html
- Migration operation for adding extensions
- -----------------------------------------
- If you need to add a PostgreSQL extension (like ``hstore``, ``postgis``, etc.)
- using a migration, use the
- :class:`~django.contrib.postgres.operations.CreateExtension` operation.
- .. _postgresql-server-side-cursors:
- Server-side cursors
- -------------------
- When using :meth:`QuerySet.iterator()
- <django.db.models.query.QuerySet.iterator>`, Django opens a :ref:`server-side
- cursor <psycopg:server-side-cursors>`. By default, PostgreSQL assumes that
- only the first 10% of the results of cursor queries will be fetched. The query
- planner spends less time planning the query and starts returning results
- faster, but this could diminish performance if more than 10% of the results are
- retrieved. PostgreSQL's assumptions on the number of rows retrieved for a
- cursor query is controlled with the `cursor_tuple_fraction`_ option.
- .. _cursor_tuple_fraction: https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION
- .. _transaction-pooling-server-side-cursors:
- Transaction pooling and server-side cursors
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Using a connection pooler in transaction pooling mode (e.g. `PgBouncer`_)
- requires disabling server-side cursors for that connection.
- Server-side cursors are local to a connection and remain open at the end of a
- transaction when :setting:`AUTOCOMMIT <DATABASE-AUTOCOMMIT>` is ``True``. A
- subsequent transaction may attempt to fetch more results from a server-side
- cursor. In transaction pooling mode, there's no guarantee that subsequent
- transactions will use the same connection. If a different connection is used,
- an error is raised when the transaction references the server-side cursor,
- because server-side cursors are only accessible in the connection in which they
- were created.
- One solution is to disable server-side cursors for a connection in
- :setting:`DATABASES` by setting :setting:`DISABLE_SERVER_SIDE_CURSORS
- <DATABASE-DISABLE_SERVER_SIDE_CURSORS>` to ``True``.
- To benefit from server-side cursors in transaction pooling mode, you could set
- up :doc:`another connection to the database </topics/db/multi-db>` in order to
- perform queries that use server-side cursors. This connection needs to either
- be directly to the database or to a connection pooler in session pooling mode.
- Another option is to wrap each ``QuerySet`` using server-side cursors in an
- :func:`~django.db.transaction.atomic` block, because it disables ``autocommit``
- for the duration of the transaction. This way, the server-side cursor will only
- live for the duration of the transaction.
- .. _PgBouncer: https://www.pgbouncer.org/
- .. _manually-specified-autoincrement-pk:
- Manually-specifying values of auto-incrementing primary keys
- ------------------------------------------------------------
- Django uses PostgreSQL's identity columns to store auto-incrementing primary
- keys. An identity column is populated with values from a `sequence`_ that keeps
- track of the next available value. Manually assigning a value to an
- auto-incrementing field doesn't update the field's sequence, which might later
- cause a conflict. For example:
- .. code-block:: pycon
- >>> 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.
- If you need to specify such values, reset the sequence afterward to avoid
- reusing a value that's already in the table. The :djadmin:`sqlsequencereset`
- management command generates the SQL statements to do that.
- .. _sequence: https://www.postgresql.org/docs/current/sql-createsequence.html
- Test database templates
- -----------------------
- You can use the :setting:`TEST['TEMPLATE'] <TEST_TEMPLATE>` setting to specify
- a `template`_ (e.g. ``'template0'``) from which to create a test database.
- .. _template: https://www.postgresql.org/docs/current/sql-createdatabase.html
- Speeding up test execution with non-durable settings
- ----------------------------------------------------
- You can speed up test execution times by `configuring PostgreSQL to be
- non-durable <https://www.postgresql.org/docs/current/non-durability.html>`_.
- .. warning::
- This is dangerous: it will make your database more susceptible to data loss
- or corruption in the case of a server crash or power loss. Only use this on
- a development machine where you can easily restore the entire contents of
- all databases in the cluster.
- .. _psycopg: https://www.psycopg.org/psycopg3/
- .. _psycopg2: https://www.psycopg.org/
- .. _mariadb-notes:
- MariaDB notes
- =============
- Django supports MariaDB 10.5 and higher.
- To use MariaDB, use the MySQL backend, which is shared between the two. See the
- :ref:`MySQL notes <mysql-notes>` for more details.
- .. _mysql-notes:
- MySQL notes
- ===========
- Version support
- ---------------
- Django supports MySQL 8.0.11 and higher.
- Django's ``inspectdb`` feature uses the ``information_schema`` database, which
- contains detailed data on all database schemas.
- Django expects the database to support Unicode (UTF-8 encoding) and delegates to
- it the task of enforcing transactions and referential integrity. It is important
- to be aware of the fact that the two latter ones aren't actually enforced by
- MySQL when using the MyISAM storage engine, see the next section.
- .. _mysql-storage-engines:
- Storage engines
- ---------------
- MySQL has several `storage engines`_. You can change the default storage engine
- in the server configuration.
- MySQL's default storage engine is InnoDB_. This engine is fully transactional
- and supports foreign key references. It's the recommended choice. However, the
- InnoDB autoincrement counter is lost on a MySQL restart because it does not
- remember the ``AUTO_INCREMENT`` value, instead recreating it as "max(id)+1".
- This may result in an inadvertent reuse of :class:`~django.db.models.AutoField`
- values.
- The main drawbacks of MyISAM_ are that it doesn't support transactions or
- enforce foreign-key constraints.
- .. _storage engines: https://dev.mysql.com/doc/refman/en/storage-engines.html
- .. _MyISAM: https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html
- .. _InnoDB: https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html
- .. _mysql-db-api-drivers:
- MySQL DB API Drivers
- --------------------
- MySQL has a couple drivers that implement the Python Database API described in
- :pep:`249`:
- - :pypi:`mysqlclient` is a native driver. It's **the recommended choice**.
- - `MySQL Connector/Python`_ is a pure Python driver from Oracle that does not
- require the MySQL client library or any Python modules outside the standard
- library.
- .. _MySQL Connector/Python: https://dev.mysql.com/downloads/connector/python/
- In addition to a DB API driver, Django needs an adapter to access the database
- drivers from its ORM. Django provides an adapter for mysqlclient while MySQL
- Connector/Python includes `its own`_.
- .. _its own: https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html
- mysqlclient
- ~~~~~~~~~~~
- Django requires `mysqlclient`_ 1.4.3 or later.
- MySQL Connector/Python
- ~~~~~~~~~~~~~~~~~~~~~~
- MySQL Connector/Python is available from the `download page`_.
- The Django adapter is available in versions 1.1.X and later. It may not
- support the most recent releases of Django.
- .. _download page: https://dev.mysql.com/downloads/connector/python/
- .. _mysql-time-zone-definitions:
- Time zone definitions
- ---------------------
- If you plan on using Django's :doc:`timezone support </topics/i18n/timezones>`,
- use `mysql_tzinfo_to_sql`_ to load time zone tables into the MySQL database.
- This needs to be done just once for your MySQL server, not per database.
- .. _mysql_tzinfo_to_sql: https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html
- Creating your database
- ----------------------
- You can `create your database`_ using the command-line tools and this SQL:
- .. code-block:: sql
- CREATE DATABASE <dbname> CHARACTER SET utf8mb4;
- This ensures all tables and columns will use UTF-8 by default.
- .. _create your database: https://dev.mysql.com/doc/refman/en/create-database.html
- .. _mysql-collation:
- Collation settings
- ~~~~~~~~~~~~~~~~~~
- The collation setting for a column controls the order in which data is sorted
- as well as what strings compare as equal. You can specify the ``db_collation``
- parameter to set the collation name of the column for
- :attr:`CharField <django.db.models.CharField.db_collation>` and
- :attr:`TextField <django.db.models.TextField.db_collation>`.
- The collation can also be set on a database-wide level and per-table. This is
- `documented thoroughly`_ in the MySQL documentation. In such cases, you must
- set the collation by directly manipulating the database settings or tables.
- Django doesn't provide an API to change them.
- .. _documented thoroughly: https://dev.mysql.com/doc/refman/en/charset.html
- By default, with a UTF-8 database, MySQL will use the
- ``utf8mb4_0900_ai_ci`` collation. This results in all string equality
- comparisons being done in a *case-insensitive* manner. That is, ``"Fred"`` and
- ``"freD"`` are considered equal at the database level. If you have a unique
- constraint on a field, it would be illegal to try to insert both ``"aa"`` and
- ``"AA"`` into the same column, since they compare as equal (and, hence,
- non-unique) with the default collation. If you want case-sensitive comparisons
- on a particular column or table, change the column or table to use the
- ``utf8mb4_0900_as_cs`` collation.
- Please note that according to `MySQL Unicode Character Sets`_, comparisons for
- the ``utf8mb4_general_ci`` collation are faster, but slightly less correct,
- than comparisons for ``utf8mb4_unicode_ci``. If this is acceptable for your
- application, you should use ``utf8mb4_general_ci`` because it is faster. If
- this is not acceptable (for example, if you require German dictionary order),
- use ``utf8mb4_unicode_ci`` because it is more accurate.
- .. _MySQL Unicode Character Sets: https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html
- .. warning::
- Model formsets validate unique fields in a case-sensitive manner. Thus when
- using a case-insensitive collation, a formset with unique field values that
- differ only by case will pass validation, but upon calling ``save()``, an
- ``IntegrityError`` will be raised.
- Connecting to the database
- --------------------------
- Refer to the :doc:`settings documentation </ref/settings>`.
- Connection settings are used in this order:
- #. :setting:`OPTIONS`.
- #. :setting:`NAME`, :setting:`USER`, :setting:`PASSWORD`, :setting:`HOST`,
- :setting:`PORT`
- #. MySQL option files.
- In other words, if you set the name of the database in :setting:`OPTIONS`,
- this will take precedence over :setting:`NAME`, which would override
- anything in a `MySQL option file`_.
- Here's a sample configuration which uses a MySQL option file::
- # settings.py
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.mysql",
- "OPTIONS": {
- "read_default_file": "/path/to/my.cnf",
- },
- }
- }
- .. code-block:: ini
- # my.cnf
- [client]
- database = NAME
- user = USER
- password = PASSWORD
- default-character-set = utf8mb4
- Several other `MySQLdb connection options`_ may be useful, such as ``ssl``,
- ``init_command``, and ``sql_mode``.
- .. _MySQL option file: https://dev.mysql.com/doc/refman/en/option-files.html
- .. _MySQLdb connection options: https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes
- .. _mysql-sql-mode:
- Setting ``sql_mode``
- ~~~~~~~~~~~~~~~~~~~~
- The default value of the ``sql_mode`` option contains ``STRICT_TRANS_TABLES``.
- That option escalates warnings into errors when data are truncated upon
- insertion, so Django highly recommends activating a `strict mode`_ for MySQL to
- prevent data loss (either ``STRICT_TRANS_TABLES`` or ``STRICT_ALL_TABLES``).
- .. _strict mode: https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict
- If you need to customize the SQL mode, you can set the ``sql_mode`` variable
- like other MySQL options: either in a config file or with the entry
- ``'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"`` in the
- :setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`.
- .. _mysql-isolation-level:
- Isolation level
- ~~~~~~~~~~~~~~~
- When running concurrent loads, database transactions from different sessions
- (say, separate threads handling different requests) may interact with each
- other. These interactions are affected by each session's `transaction isolation
- level`_. You can set a connection's isolation level with an
- ``'isolation_level'`` entry in the :setting:`OPTIONS` part of your database
- configuration in :setting:`DATABASES`. Valid values for
- this entry are the four standard isolation levels:
- * ``'read uncommitted'``
- * ``'read committed'``
- * ``'repeatable read'``
- * ``'serializable'``
- or ``None`` to use the server's configured isolation level. However, Django
- works best with and defaults to read committed rather than MySQL's default,
- repeatable read. Data loss is possible with repeatable read. In particular,
- you may see cases where :meth:`~django.db.models.query.QuerySet.get_or_create`
- will raise an :exc:`~django.db.IntegrityError` but the object won't appear in
- a subsequent :meth:`~django.db.models.query.QuerySet.get` call.
- .. _transaction isolation level: https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html
- Creating your tables
- --------------------
- When Django generates the schema, it doesn't specify a storage engine, so
- tables will be created with whatever default storage engine your database
- server is configured for. The easiest solution is to set your database server's
- default storage engine to the desired engine.
- If you're using a hosting service and can't change your server's default
- storage engine, you have a couple of options.
- * After the tables are created, execute an ``ALTER TABLE`` statement to
- convert a table to a new storage engine (such as InnoDB):
- .. code-block:: sql
- ALTER TABLE <tablename> ENGINE=INNODB;
- This can be tedious if you have a lot of tables.
- * Another option is to use the ``init_command`` option for MySQLdb prior to
- creating your tables::
- "OPTIONS": {
- "init_command": "SET default_storage_engine=INNODB",
- }
- This sets the default storage engine upon connecting to the database.
- After your tables have been created, you should remove this option as it
- adds a query that is only needed during table creation to each database
- connection.
- Table names
- -----------
- There are `known issues`_ in even the latest versions of MySQL that can cause the
- case of a table name to be altered when certain SQL statements are executed
- under certain conditions. It is recommended that you use lowercase table
- names, if possible, to avoid any problems that might arise from this behavior.
- Django uses lowercase table names when it auto-generates table names from
- models, so this is mainly a consideration if you are overriding the table name
- via the :class:`~django.db.models.Options.db_table` parameter.
- .. _known issues: https://bugs.mysql.com/bug.php?id=48875
- Savepoints
- ----------
- Both the Django ORM and MySQL (when using the InnoDB :ref:`storage engine
- <mysql-storage-engines>`) support database :ref:`savepoints
- <topics-db-transactions-savepoints>`.
- If you use the MyISAM storage engine please be aware of the fact that you will
- receive database-generated errors if you try to use the :ref:`savepoint-related
- methods of the transactions API <topics-db-transactions-savepoints>`. The reason
- for this is that detecting the storage engine of a MySQL database/table is an
- expensive operation so it was decided it isn't worth to dynamically convert
- these methods in no-op's based in the results of such detection.
- Notes on specific fields
- ------------------------
- .. _mysql-character-fields:
- Character fields
- ~~~~~~~~~~~~~~~~
- Any fields that are stored with ``VARCHAR`` column types may have their
- ``max_length`` restricted to 255 characters if you are using ``unique=True``
- for the field. This affects :class:`~django.db.models.CharField`,
- :class:`~django.db.models.SlugField`. See `the MySQL documentation`_ for more
- details.
- .. _the MySQL documentation: https://dev.mysql.com/doc/refman/en/create-index.html#create-index-column-prefixes
- ``TextField`` limitations
- ~~~~~~~~~~~~~~~~~~~~~~~~~
- MySQL can index only the first N chars of a ``BLOB`` or ``TEXT`` column. Since
- ``TextField`` doesn't have a defined length, you can't mark it as
- ``unique=True``. MySQL will report: "BLOB/TEXT column '<db_column>' used in key
- specification without a key length".
- .. _mysql-fractional-seconds:
- Fractional seconds support for Time and DateTime fields
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- MySQL can store fractional seconds, provided that the column definition
- includes a fractional indication (e.g. ``DATETIME(6)``).
- Django will not upgrade existing columns to include fractional seconds if the
- database server supports it. If you want to enable them on an existing database,
- it's up to you to either manually update the column on the target database, by
- executing a command like:
- .. code-block:: sql
- ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
- or using a :class:`~django.db.migrations.operations.RunSQL` operation in a
- :ref:`data migration <data-migrations>`.
- ``TIMESTAMP`` columns
- ~~~~~~~~~~~~~~~~~~~~~
- If you are using a legacy database that contains ``TIMESTAMP`` columns, you must
- set :setting:`USE_TZ = False <USE_TZ>` to avoid data corruption.
- :djadmin:`inspectdb` maps these columns to
- :class:`~django.db.models.DateTimeField` and if you enable timezone support,
- both MySQL and Django will attempt to convert the values from UTC to local time.
- Row locking with ``QuerySet.select_for_update()``
- -------------------------------------------------
- MySQL and MariaDB do not support some options to the ``SELECT ... FOR UPDATE``
- statement. If ``select_for_update()`` is used with an unsupported option, then
- a :exc:`~django.db.NotSupportedError` is raised.
- =============== ========= =====
- Option MariaDB MySQL
- =============== ========= =====
- ``SKIP LOCKED`` X (≥10.6) X
- ``NOWAIT`` X X
- ``OF`` X
- ``NO KEY``
- =============== ========= =====
- When using ``select_for_update()`` on MySQL, make sure you filter a queryset
- against at least a set of fields contained in unique constraints or only
- against fields covered by indexes. Otherwise, an exclusive write lock will be
- acquired over the full table for the duration of the transaction.
- Automatic typecasting can cause unexpected results
- --------------------------------------------------
- When performing a query on a string type, but with an integer value, MySQL will
- coerce the types of all values in the table to an integer before performing the
- comparison. If your table contains the values ``'abc'``, ``'def'`` and you
- query for ``WHERE mycolumn=0``, both rows will match. Similarly, ``WHERE mycolumn=1``
- will match the value ``'abc1'``. Therefore, string type fields included in Django
- will always cast the value to a string before using it in a query.
- If you implement custom model fields that inherit from
- :class:`~django.db.models.Field` directly, are overriding
- :meth:`~django.db.models.Field.get_prep_value`, or use
- :class:`~django.db.models.expressions.RawSQL`,
- :meth:`~django.db.models.query.QuerySet.extra`, or
- :meth:`~django.db.models.Manager.raw`, you should ensure that you perform
- appropriate typecasting.
- .. _sqlite-notes:
- SQLite notes
- ============
- Django supports SQLite 3.31.0 and later.
- SQLite_ provides an excellent development alternative for applications that
- are predominantly read-only or require a smaller installation footprint. As
- with all database servers, though, there are some differences that are
- specific to SQLite that you should be aware of.
- .. _SQLite: https://www.sqlite.org/
- .. _sqlite-string-matching:
- Substring matching and case sensitivity
- ---------------------------------------
- For all SQLite versions, there is some slightly counterintuitive behavior when
- attempting to match some types of strings. These are triggered when using the
- :lookup:`iexact` or :lookup:`contains` filters in Querysets. The behavior
- splits into two cases:
- 1. For substring matching, all matches are done case-insensitively. That is a
- filter such as ``filter(name__contains="aa")`` will match a name of ``"Aabb"``.
- 2. For strings containing characters outside the ASCII range, all exact string
- matches are performed case-sensitively, even when the case-insensitive options
- are passed into the query. So the :lookup:`iexact` filter will behave exactly
- the same as the :lookup:`exact` filter in these cases.
- Some possible workarounds for this are `documented at sqlite.org`_, but they
- aren't utilized by the default SQLite backend in Django, as incorporating them
- would be fairly difficult to do robustly. Thus, Django exposes the default
- SQLite behavior and you should be aware of this when doing case-insensitive or
- substring filtering.
- .. _documented at sqlite.org: https://www.sqlite.org/faq.html#q18
- .. _sqlite-decimal-handling:
- Decimal handling
- ----------------
- SQLite has no real decimal internal type. Decimal values are internally
- converted to the ``REAL`` data type (8-byte IEEE floating point number), as
- explained in the `SQLite datatypes documentation`__, so they don't support
- correctly-rounded decimal floating point arithmetic.
- __ https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
- "Database is locked" errors
- ---------------------------
- SQLite is meant to be a lightweight database, and thus can't support a high
- level of concurrency. ``OperationalError: database is locked`` errors indicate
- that your application is experiencing more concurrency than ``sqlite`` can
- handle in default configuration. This error means that one thread or process has
- an exclusive lock on the database connection and another thread timed out
- waiting for the lock the be released.
- Python's SQLite wrapper has
- a default timeout value that determines how long the second thread is allowed to
- wait on the lock before it times out and raises the ``OperationalError: database
- is locked`` error.
- If you're getting this error, you can solve it by:
- * Switching to another database backend. At a certain point SQLite becomes
- too "lite" for real-world applications, and these sorts of concurrency
- errors indicate you've reached that point.
- * Rewriting your code to reduce concurrency and ensure that database
- transactions are short-lived.
- * Increase the default timeout value by setting the ``timeout`` database
- option::
- "OPTIONS": {
- # ...
- "timeout": 20,
- # ...
- }
- This will make SQLite wait a bit longer before throwing "database is locked"
- errors; it won't really do anything to solve them.
- .. _sqlite-transaction-behavior:
- Transactions behavior
- ~~~~~~~~~~~~~~~~~~~~~
- .. versionadded:: 5.1
- SQLite supports three transaction modes: ``DEFERRED``, ``IMMEDIATE``, and
- ``EXCLUSIVE``.
- The default is ``DEFERRED``. If you need to use a different mode, set it in the
- :setting:`OPTIONS` part of your database configuration in
- :setting:`DATABASES`, for example::
- "OPTIONS": {
- # ...
- "transaction_mode": "IMMEDIATE",
- # ...
- }
- To make sure your transactions wait until ``timeout`` before raising "Database
- is Locked", change the transaction mode to ``IMMEDIATE``.
- For the best performance with ``IMMEDIATE`` and ``EXCLUSIVE``, transactions
- should be as short as possible. This might be hard to guarantee for all of your
- views so the usage of :setting:`ATOMIC_REQUESTS <DATABASE-ATOMIC_REQUESTS>` is
- discouraged in this case.
- For more information see `Transactions in SQLite`_.
- .. _`Transactions in SQLite`: https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
- ``QuerySet.select_for_update()`` not supported
- ----------------------------------------------
- SQLite does not support the ``SELECT ... FOR UPDATE`` syntax. Calling it will
- have no effect.
- .. _sqlite-isolation:
- Isolation when using ``QuerySet.iterator()``
- --------------------------------------------
- There are special considerations described in `Isolation In SQLite`_ when
- modifying a table while iterating over it using :meth:`.QuerySet.iterator`. If
- a row is added, changed, or deleted within the loop, then that row may or may
- not appear, or may appear twice, in subsequent results fetched from the
- iterator. Your code must handle this.
- .. _`Isolation in SQLite`: https://www.sqlite.org/isolation.html
- .. _sqlite-json1:
- Enabling JSON1 extension on SQLite
- ----------------------------------
- To use :class:`~django.db.models.JSONField` on SQLite, you need to enable the
- `JSON1 extension`_ on Python's :py:mod:`sqlite3` library. If the extension is
- not enabled on your installation, a system error (``fields.E180``) will be
- raised.
- To enable the JSON1 extension you can follow the instruction on
- `the wiki page`_.
- .. note::
- The JSON1 extension is enabled by default on SQLite 3.38+.
- .. _JSON1 extension: https://www.sqlite.org/json1.html
- .. _the wiki page: https://code.djangoproject.com/wiki/JSON1Extension
- .. _sqlite-init-command:
- Setting pragma options
- ----------------------
- .. versionadded:: 5.1
- `Pragma options`_ can be set upon connection by using the ``init_command`` in
- the :setting:`OPTIONS` part of your database configuration in
- :setting:`DATABASES`. The example below shows how to enable extra durability of
- synchronous writes and change the ``cache_size``::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.sqlite3",
- # ...
- "OPTIONS": {
- "init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
- },
- }
- }
- .. _Pragma options: https://www.sqlite.org/pragma.html
- .. _oracle-notes:
- Oracle notes
- ============
- Django supports `Oracle Database Server`_ versions 19c and higher. Version
- 1.3.2 or higher of the `oracledb`_ Python driver is required.
- .. deprecated:: 5.0
- Support for ``cx_Oracle`` is deprecated.
- .. _`Oracle Database Server`: https://www.oracle.com/
- .. _`oracledb`: https://oracle.github.io/python-oracledb/
- In order for the ``python manage.py migrate`` command to work, your Oracle
- database user must have privileges to run the following commands:
- * CREATE TABLE
- * CREATE SEQUENCE
- * CREATE PROCEDURE
- * CREATE TRIGGER
- To run a project's test suite, the user usually needs these *additional*
- privileges:
- * CREATE USER
- * ALTER USER
- * DROP USER
- * CREATE TABLESPACE
- * DROP TABLESPACE
- * CREATE SESSION WITH ADMIN OPTION
- * CREATE TABLE WITH ADMIN OPTION
- * CREATE SEQUENCE WITH ADMIN OPTION
- * CREATE PROCEDURE WITH ADMIN OPTION
- * CREATE TRIGGER WITH ADMIN OPTION
- While the ``RESOURCE`` role has the required ``CREATE TABLE``,
- ``CREATE SEQUENCE``, ``CREATE PROCEDURE``, and ``CREATE TRIGGER`` privileges,
- and a user granted ``RESOURCE WITH ADMIN OPTION`` can grant ``RESOURCE``, such
- a user cannot grant the individual privileges (e.g. ``CREATE TABLE``), and thus
- ``RESOURCE WITH ADMIN OPTION`` is not usually sufficient for running tests.
- Some test suites also create views or materialized views; to run these, the
- user also needs ``CREATE VIEW WITH ADMIN OPTION`` and
- ``CREATE MATERIALIZED VIEW WITH ADMIN OPTION`` privileges. In particular, this
- is needed for Django's own test suite.
- All of these privileges are included in the DBA role, which is appropriate
- for use on a private developer's database.
- The Oracle database backend uses the ``SYS.DBMS_LOB`` and ``SYS.DBMS_RANDOM``
- packages, so your user will require execute permissions on it. It's normally
- accessible to all users by default, but in case it is not, you'll need to grant
- permissions like so:
- .. code-block:: sql
- GRANT EXECUTE ON SYS.DBMS_LOB TO user;
- GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
- Connecting to the database
- --------------------------
- To connect using the service name of your Oracle database, your ``settings.py``
- file should look something like this::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.oracle",
- "NAME": "xe",
- "USER": "a_user",
- "PASSWORD": "a_password",
- "HOST": "",
- "PORT": "",
- }
- }
- In this case, you should leave both :setting:`HOST` and :setting:`PORT` empty.
- However, if you don't use a ``tnsnames.ora`` file or a similar naming method
- and want to connect using the SID ("xe" in this example), then fill in both
- :setting:`HOST` and :setting:`PORT` like so::
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.oracle",
- "NAME": "xe",
- "USER": "a_user",
- "PASSWORD": "a_password",
- "HOST": "dbprod01ned.mycompany.com",
- "PORT": "1540",
- }
- }
- You should either supply both :setting:`HOST` and :setting:`PORT`, or leave
- both as empty strings. Django will use a different connect descriptor depending
- on that choice.
- Full DSN and Easy Connect
- ~~~~~~~~~~~~~~~~~~~~~~~~~
- A Full DSN or Easy Connect string can be used in :setting:`NAME` if both
- :setting:`HOST` and :setting:`PORT` are empty. This format is required when
- using RAC or pluggable databases without ``tnsnames.ora``, for example.
- Example of an Easy Connect string::
- "NAME": "localhost:1521/orclpdb1"
- Example of a full DSN string::
- "NAME": (
- "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
- "(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
- )
- Threaded option
- ---------------
- If you plan to run Django in a multithreaded environment (e.g. Apache using the
- default MPM module on any modern operating system), then you **must** set
- the ``threaded`` option of your Oracle database configuration to ``True``::
- "OPTIONS": {
- "threaded": True,
- }
- Failure to do this may result in crashes and other odd behavior.
- INSERT ... RETURNING INTO
- -------------------------
- By default, the Oracle backend uses a ``RETURNING INTO`` clause to efficiently
- retrieve the value of an ``AutoField`` when inserting new rows. This behavior
- may result in a ``DatabaseError`` in certain unusual setups, such as when
- inserting into a remote table, or into a view with an ``INSTEAD OF`` trigger.
- The ``RETURNING INTO`` clause can be disabled by setting the
- ``use_returning_into`` option of the database configuration to ``False``::
- "OPTIONS": {
- "use_returning_into": False,
- }
- In this case, the Oracle backend will use a separate ``SELECT`` query to
- retrieve ``AutoField`` values.
- Naming issues
- -------------
- Oracle imposes a name length limit of 30 characters. To accommodate this, the
- backend truncates database identifiers to fit, replacing the final four
- characters of the truncated name with a repeatable MD5 hash value.
- Additionally, the backend turns database identifiers to all-uppercase.
- To prevent these transformations (this is usually required only when dealing
- with legacy databases or accessing tables which belong to other users), use
- a quoted name as the value for ``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"'
- Quoted names can also be used with Django's other supported database
- backends; except for Oracle, however, the quotes have no effect.
- When running ``migrate``, an ``ORA-06552`` error may be encountered if
- certain Oracle keywords are used as the name of a model field or the
- value of a ``db_column`` option. Django quotes all identifiers used
- in queries to prevent most such problems, but this error can still
- occur when an Oracle datatype is used as a column name. In
- particular, take care to avoid using the names ``date``,
- ``timestamp``, ``number`` or ``float`` as a field name.
- .. _oracle-null-empty-strings:
- NULL and empty strings
- ----------------------
- Django generally prefers to use the empty string (``''``) rather than
- ``NULL``, but Oracle treats both identically. To get around this, the
- Oracle backend ignores an explicit ``null`` option on fields that
- have the empty string as a possible value and generates DDL as if
- ``null=True``. When fetching from the database, it is assumed that
- a ``NULL`` value in one of these fields really means the empty
- string, and the data is silently converted to reflect this assumption.
- ``TextField`` limitations
- -------------------------
- The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes
- some limitations on the usage of such LOB columns in general:
- * LOB columns may not be used as primary keys.
- * LOB columns may not be used in indexes.
- * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that
- attempting to use the ``QuerySet.distinct`` method on a model that
- includes ``TextField`` columns will result in an ``ORA-00932`` error when
- run against Oracle. As a workaround, use the ``QuerySet.defer`` method in
- conjunction with ``distinct()`` to prevent ``TextField`` columns from being
- included in the ``SELECT DISTINCT`` list.
- .. _subclassing-database-backends:
- Subclassing the built-in database backends
- ==========================================
- Django comes with built-in database backends. You may subclass an existing
- database backends to modify its behavior, features, or configuration.
- Consider, for example, that you need to change a single database feature.
- First, you have to create a new directory with a ``base`` module in it. For
- example:
- .. code-block:: text
- mysite/
- ...
- mydbengine/
- __init__.py
- base.py
- The ``base.py`` module must contain a class named ``DatabaseWrapper`` that
- subclasses an existing engine from the ``django.db.backends`` module. Here's an
- example of subclassing the PostgreSQL engine to change a feature class
- ``allows_group_by_selected_pks_on_model``:
- .. code-block:: python
- :caption: ``mysite/mydbengine/base.py``
- from 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
- Finally, you must specify a :setting:`DATABASE-ENGINE` in your ``settings.py``
- file::
- DATABASES = {
- "default": {
- "ENGINE": "mydbengine",
- # ...
- },
- }
- You can see the current list of database engines by looking in
- :source:`django/db/backends`.
- .. _third-party-notes:
- Using a 3rd-party database backend
- ==================================
- In addition to the officially supported databases, there are backends provided
- by 3rd parties that allow you to use other databases with Django:
- * :pypi:`CockroachDB <django-cockroachdb>`
- * :pypi:`Firebird <django-firebird>`
- * :pypi:`Google Cloud Spanner <django-google-spanner>`
- * :pypi:`Microsoft SQL Server <mssql-django>`
- * :pypi:`Snowflake <django-snowflake>`
- * :pypi:`TiDB <django-tidb>`
- * :pypi:`YugabyteDB <django-yugabytedb>`
- The Django versions and ORM features supported by these unofficial backends
- vary considerably. Queries regarding the specific capabilities of these
- unofficial backends, along with any support queries, should be directed to
- the support channels provided by each 3rd party project.
|