revision-up-to: | 11321 (1.1) unfinished |
---|
Django は可能な限り全てのデータベースバックエンドをサポートしようとしていま すが、残念ながら全てのサーバが全く同じ仕様というわけではないので、どの機能 をサポートすべきか、どういった仕様を仮定するかといった設計上の判断を下して います。
このドキュメントでは、このドキュメントでは、 Django を使う上で関係のあるデー タベース機能について説明します。ただし、このドキュメントは特定のデータベー スサーバ向けのドキュメントとして書かれたものではなく、リファレンスマニュア ルでもありません。
The implementation of the population statistics aggregates STDDEV_POP
and
VAR_POP
that shipped with PostgreSQL 8.2 to 8.2.4 are known to be
faulty. Users of these releases of PostgreSQL are advised to upgrade to
Release 8.2.5 or later. Django will raise a NotImplementedError
if you
attempt to use the StdDev(sample=False)
or Variance(sample=False)
aggregate with a database backend that falls within the affected release range.
By default, Django starts a transaction when a database connection is first used and commits the result at the end of the request/response handling. The PostgreSQL backends normally operate the same as any other Django backend in this respect.
If your application is particularly read-heavy and doesn’t make many database
writes, the overhead of a constantly open transaction can sometimes be
noticeable. For those situations, if you’re using the postgresql_psycopg2
backend, you can configure Django to use “autocommit” behavior for the
connection, meaning that each database operation will normally be in its own
transaction, rather than having the transaction extend over multiple
operations. In this case, you can still manually start a transaction if you’re
doing something that requires consistency across multiple database operations.
The autocommit behavior is enabled by setting the autocommit
key in the
DATABASE_OPTIONS
setting:
DATABASE_OPTIONS = {
"autocommit": True,
}
In this configuration, Django still ensures that delete() and update() queries run inside a single transaction, so that either all the affected objects are changed or none of them are.
This is database-level autocommit
This functionality is not the same as the
topics-db-transactions-autocommit decorator. That decorator is a
Django-level implementation that commits automatically after data changing
operations. The feature enabled using the DATABASE_OPTIONS
settings provides autocommit behavior at the database adapter level. It
commits after every operation.
If you are using this feature and performing an operation akin to delete or updating that requires multiple operations, you are strongly recommended to wrap you operations in manual transaction handling to ensure data consistency. You should also audit your existing code for any instances of this behavior before enabling this feature. It’s faster, but it provides less automatic protection for multi-call operations.
Django はデータベースがトランザクションや参照の一貫性 (referential integrity)、 Unicode (UTF-8 エンコーディング) をサポートしていることを想定 して書かれています。好運なことに、 MySQL バージョン 3.23 以降でこれらの機 能全てをサポートしています。従って、 3.23 や 4.0 をバックエンドとして使うの は可能なのですが、 4.1 や 5.0 を使った方がトラブルに巻き込まれにくいでしょ う。
MySQL 4.1 では、文字セットのサポートを大幅に改良しています。 4.1 では、 データベース全体から、テーブル毎、カラム毎にいたるまで個別にデフォルトの文 字セットを指定できます。以前のバージョンでは、サーバ全体に対する文字セット の設定しかできませんでした。また、 4.1 になってはじめてオンザフライで文字セッ トを変更できるようになりました。 4.1 にはビューのサポートもありますが、 Django はまだこの機能をサポートしていません。
MySQL 5.0 では、全てのデータベーススキーマに関する詳細なデータの入った
information_schema
というデータベースが追加されました。
information_schema
が存在すると、 Django はこのデータベースに対して
inspectdb
機能を適用します。 5.0 ではまた、ストアドプロシジャのサポート
も追加されましたが、 Django はまだこの機能をサポートしていません。
MySQL は複数の ストレージエンジン (以前はテーブルタイプ: table type と呼 ばれていたもの) を選択できます。デフォルトのストレージエンジンはサーバ設定 で変更できます。
デフォルトのストレージエンジンは MyISAM [1] です。 MyISAM の短所は、現状 ではトランザクションや外部キーをサポートしていないという点です。一方、 MyISAM は、現状で、全文インデクスの生成や全文検索をサポートしている唯一のス トレージエンジンでもあります。
InnoDB エンジンは完全なトランザクション機能と外部キー参照をサポートしてい ます。
BDB エンジンは InnoDB と同様、完全なトランザクション機能を外部キー参照をサ ポートしていますが、やや時代送れになりつつあるようです。
SolidDB や Falcon といった その他のストレージエンジン まだまだ圏外の話です。現状では、おそらく InnoDB が最良の選択でしょう。
[1] | お使いの MySQL パッケージでデフォルトが変更されていない場合。 Windows Community Server 向けのインストーラは、デフォルトのストレージエ ンジンを InnoDB にしているという報告があります。 |
MySQLdb は Python から MySQL にアクセスするためのインタフェースです。 Django から利用できる MySQL の全ての機能を使うには、 バージョン 1.2.1p2 以 降が必要です。
Note
MySQLdb を Django から使おうとして
ImportError: cannot import name ImmutableSet
が出る場合は、おそらく
MySQLdb に古い sets.py
ファイルが入っていて、 Python 2.4 の同名の組
み込みモジュールと衝突しています。この問題を回避するには、 1.2.1p2 以降
の MySQLdb をインストールしてください。上書きインストールした場合には、
MySQLdb のインストールディレクトリを調べ、以前のバージョンの
sets.py
が入っていれば除去してください。
コマンドラインツールを使って、以下の SQL を発行すれば データベースを作成 できます:
CREATE DATABASE <dbname> CHARACTER SET utf8;
これで、全てのテーブルとカラムがデフォルトで UTF-8 を使うようになります。
カラムのコレーション設定は、データの保存方法や、文字列の等価性の定義を制御 しています。コレーションはデータベース全体でも、テーブル単位でも、カラム単 位でも設定できます。コレーションの詳細は MySQL のドキュメントで 詳しく解説されています 。いずれの場合でも、 コレーションの設定は直接データベーステーブルに対して行ってください。 Django はモデル定義でコレーションを設定する方法を提供していません。
デフォルトの構成では、 MySQL は UTF-8 のデータベースに対して
utf8_general_ci_swedish
コレーションを使います。この設定では、全ての文
字列の等値比較が 大小文字を区別 せず行われます。つまり、 "Fred"
と
"freD"
はデータベースレベルでは同じ値だとみなされるのです。そのため、デ
フォルトのコレーションを使っていると、フィールドに unique
制約をかけた
ときに、 "aa"
と "AA"
は等しいとみなされ (一意性が破れるので) 同じ
カラムに入れられなくなります。
大抵のケースでは、デフォルトの設定はさして問題を起こしません。しかし、特定
のカラムやテーブルで大小文字を区別させたいなら、そのカラムやテーブルに
utf8_bin
コレーションを指定せねばなりません。その場合、注意すべきなのは、
MySQLdb 1.2.2 を使っていると、 Django のデータベースバックエンドが、データ
ベースから取り出した文字列フィールドの値として (unicode 文字列ではなく)
bytestring を返すということです。このふるまいは、 常に unicode を返す、と
いう Django の通常のやりかたから大きくかけ離れています。コレーションを
utf8_bin
にして、 bytestring を受け取ったときの扱いは、開発者に委ねられ
ています。 Django 自体はこのカラムを問題なく扱えますが、一貫性をもってデー
タを処理したければ、 django.utils.encoding.smart_unicode()
を何度も
呼び出すことになるでしょう。(データベースバックエンドレイヤとモデルの操作レ
イヤは内部的に分離しているため、変換が必要かどうかをデータベースレイヤでは
判断できないので) Django はこの変換に関知しないのです。
MySQLdb 1.2.1p2 を使っているなら、コレーションを utf8_bin
にしても、
CharField
は unicode 文字列を返します。しかし、
今度は TextField
が (Python 標準モジュール
array
の) array.array
を返します。データをデータベースから読み出す
ときに、変換に必要な情報が手にはいらないので、 Django 側ではどうしようもあ
りません。この問題は MySQLdb 1.2.2 で解決済み
なので、 itf8_bin
コレーションで TextField
を使いたければ、バージョンを 1.2.2 に上げて、バイト文字列として扱うよう勧め
ます (それほど難しくはありません)。
MySQLdb 1.2.1p2 で utf8_bin
コレーションの設定されたテーブルを使うのな
ら、 django.contrib.sessions.models.Session
のテーブル
(通常は django_session
) や、
django.contrib.admin.models.LogEntry
のテーブル
(通常は django_admin_log
) のコレーションに
utf8_collation_ci_swedish
(デフォルトのコレーション) を使わねばなりませ
ん。これらは標準の Django のテーブルのうち、内部的に
TextField
を使っているからです。
設定に関するドキュメント を参照してください。
接続に関する設定は、以下の順に適用されます:
DATABASE_OPTIONS
DATABASE_NAME
,DATABASE_USER
,DATABASE_PASSWORD
,DATABASE_HOST
,DATABASE_PORT
- MySQL のオプション設定ファイル
別の言い方をするなら、 DATABASE_OPTIONS
内にデータベースの名前を
設定すると、その内容は DATABASE_NAME
よりも優先順位が高くなり、
さらに DATABASE_NAME
は MySQL のオプション設定ファイル の内容
をオーバライドするということです。
MySQL のオプション設定ファイルを使う例を以下に示します:
# settings.py
DATABASE_ENGINE = "mysql"
DATABASE_OPTIONS = {
'read_default_file': '/path/to/my.cnf',
}
# my.cnf
[client]
database = DATABASE_NAME
user = DATABASE_USER
password = DATABASE_PASSWORD
default-character-set = utf8
この他にも、MySQLdb の接続オプションには、 ssl
, use_unicode
,
init_command
, sql_mode
といった便利なものがあります。詳しくは
MySQLdb のドキュメント を参照してください。
Django はスキーマを作成する際にストレージエンジンを指定しません。そのため、 テーブルは常にサーバに設定されたデフォルトのストレージエンジンで作成されま す。作成されるテーブルを特定のタイプにしたければ、データベースサーバのデフォ ルトストレージエンジンを Django で使いたいストレージエンジンに合わせるのが 一番簡単です。
ホスティングサービスを使っていて、サーバのデフォルトのストレージエンジンを 変更できない場合、二つの選択肢があります。
テーブルが作成された後に、以下のようなクエリを発行して、ストレージ エンジンを (InnoDB) などに変更します:
ALTER TABLE <tablename> ENGINE=INNODB;テーブルが沢山ある場合には、これは相当骨がおれることでしょう。
あるいは、テーブルを作成する前に、 MySQLdb の
init_command
オプショ ンを使います:DATABASE_OPTIONS = { "init_command": "SET storage_engine=INNODB", }このように設定しておくと、接続時にデフォルトのストレージエンジンが変更 されます。ただし、テーブルが全て作成され、運用環境で動き始めたら、この オプションを外しておかねばなりません。
syncdb 時にストレージエンジンを変更するもう一つの方法は、 Wiki の AlterModelOnSyncDB に記載されています。
BooleanField
¶MySQL には直接的な BOOLEAN
カラム型がないので、 Django は
BooleanField
の値を TINYINT
カラムを使って 0
または 1 で保存します。詳しくはモデルフィールドのドキュメントを参照してくだ
さい。ただし、フィールドの値を出力したり、値が True
や False
でなけ
ればならないような場合を除いて、特に問題はありません。
Any fields that are stored with VARCHAR
column types have their
max_length
restricted to 255 characters if you are using unique=True
for the field. This affects CharField
,
SlugField
and
CommaSeparatedIntegerField
.
Furthermore, if you are using a version of MySQL prior to 5.0.3, all of those
column types have a maximum length restriction of 255 characters, regardless
of whether unique=True
is specified or not.
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 doesn’t support case-insensitive matching for non-ASCII strings. Some
possible workarounds for this are documented at sqlite.org, but they are
not utilised by the default SQLite backend in Django. Therefore, if you are
using the iexact
lookup type in your queryset filters, be aware that it
will not work as expected for non-ASCII strings.
Versions of SQLite 3.3.5 and older contains the following bugs:
- A bug when handling
ORDER BY
parameters. This can cause problems when you use theselect
parameter for theextra()
QuerySet method. The bug can be identified by the error messageOperationalError: ORDER BY terms must not be non-integer constants
.- A bug when handling aggregation together with DateFields and DecimalFields.
SQLite 3.3.6 was released in April 2006, so most current binary distributions
for different platforms include newer version of SQLite usable from Python
through either the pysqlite2
or the sqlite3
modules.
However, some platform/Python version combinations include older versions of SQLite (e.g. the official binary distribution of Python 2.5 for Windows, 2.5.4 as of this writing, includes SQLite 3.3.4). There are (as of Django 1.1) even some tests in the Django test suite that will fail when run under this setup.
As described below, this can be solved
by downloading and installing a newer version of pysqlite2
(pysqlite-2.x.x.win32-py2.5.exe
in the described case) that includes and
uses a newer version of SQLite. Python 2.6 for Windows ships with a version of
SQLite that is not affected by these issues.
The Ubuntu “Intrepid Ibex” (8.10) SQLite 3.5.9-3 package contains a bug that causes problems with the evaluation of query expressions. If you are using Ubuntu “Intrepid Ibex”, you will need to update the package to version 3.5.9-3ubuntu1 or newer (recommended) or find an alternate source for SQLite packages, or install SQLite from source.
At one time, Debian Lenny shipped with the same malfunctioning SQLite 3.5.9-3 package. However the Debian project has subsequently issued updated versions of the SQLite package that correct these bugs. If you find you are getting unexpected results under Debian, ensure you have updated your SQLite package to 3.5.9-5 or later.
The problem does not appear to exist with other versions of SQLite packaged with other operating systems.
SQLite version 3.6.2 (released August 30, 2008) introduced a bug into SELECT
DISTINCT
handling that is triggered by, amongst other things, Django’s
DateQuerySet
(returned by the dates()
method on a queryset).
You should avoid using this version of SQLite with Django. Either upgrade to 3.6.3 (released September 22, 2008) or later, or downgrade to an earlier version of SQLite.
For versions of Python 2.5 or newer that include sqlite3
in the standard
library Django will now use a pysqlite2
interface in preference to
sqlite3
if it finds one is available.
This provides the ability to upgrade both the DB-API 2.0 interface or SQLite 3 itself to versions newer than the ones included with your particular Python binary distribution, if needed.
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 option:DATABASE_OPTIONS = { # ... "timeout": 20, # ... }This will simply make SQLite wait a bit longer before throwing “database is locked” errors; it won’t really do anything to solve them.
Django はバージョン 9i 以降の Oracle データベースサーバ をサポートしてい
ます。 Django の regex
および iregex
クエリオペレータを使うには、
バージョン 10g 以降の Oracle を使う必要があります。
バージョン 4.3.1 以降の cx_Oracle ドライバが必要です。
Note that due to a Unicode-corruption bug in cx_Oracle
5.0, that
version of the driver should not be used with Django;
cx_Oracle
5.0.1 resolved this issue, so if you’d like to use a
more recent cx_Oracle
, use version 5.0.1.
Oracle で python manage.py syncdb
コマンドを動かすには、データベースユー
ザに以下のコマンドを実行できる権限が必要です:
- CREATE TABLE
- CREATE SEQUENCE
- CREATE PROCEDURE
- CREATE TRIGGER
Django のテストスイートを実行させるには、 さらに 以下の権限が必要です:
- CREATE USER
- DROP USER
- CREATE TABLESPACE
- DROP TABLESPACE
- CONNECT WITH ADMIN OPTION
- RESOURCE WITH ADMIN OPTION
Oracle を使う場合、 Django の settings.py は以下のように設定します:
DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = ''
DATABASE_PORT = ''
tnsnames.ora
ファイルや、 SID として扱われる名前 (上の例では “xe”)
を使わない場合は、以下のように DATABASE_HOST
および
DATABASE_PORT
を設定してください:
DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = 'dbprod01ned.mycompany.com'
DATABASE_PORT = '1540'
DATABASE_HOST
と DATABASE_PORT
は、両方とも指定するか、
両方とも空にするかどちらかにしてください。
Oracle ベースのシステムでパフォーマンス向上に使われているパラダイムとして、
「 テーブルスペース (tablespace)」によるディスクレイアウトの構築がありま
す。 db_tablespace
オプションを Meta
と Field
クラスに追加する
と、 Oracle バックエンドはテーブルスペースを利用します (バックエンドがテー
ブルスペースをサポートしなければ、 Django はこのオプションを無視します)。
モデルのテーブルにテーブルスペースを指定するには、モデルの内部クラス
Meta
に db_tablespace
オプションを指定します。モデル全体とは別のテー
ブルスペースをフィールドのカラムインデクスに指定したければ、フィールドのコ
ンストラクタに db_tablespace
を指定します。カラムごとにインデクスを生成
しない場合には、 db_tablespace
オプションは無視されます:
class TablespaceExample(models.Model):
name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")
data = models.CharField(max_length=255, db_index=True)
edges = models.ManyToManyField(to="self", db_tablespace="indexes")
class Meta:
db_tablespace = "tables"
上の例では、 TablespaceExample
モデルの生成するテーブル
(モデルテーブルと多対多のリレーションのテーブル) は、 tables
という名前
のテーブルスペースに保存されます。 name
フィールドと、多対多リレーショ
ンテーブルのインデクスは indexes
テーブルスペースに保存されます。
data
フィールドもインデクスを生成しますが、このインデクスのテーブルスペー
スは指定されていないので、デフォルトの挙動としてテーブルスペース
tables
に保存されます。
db_tablespace
オプションのデフォルト値を指定するには、
DEFAULT_TABLESPACE
および DEFAULT_INDEX_TABLESPACE
設
定を使います。これらの設定は、組み込みの Django アプリケーションや、ソース
コードをいじれないアプリケーションに対してテーブルスペースを指定する場合に
便利です。
Django 自体にはテーブルスペースを作成する機能はありません。 テーブルスペースの作成や管理の方法は、 Oracle のドキュメント を参照して ください。
Oracle は名前の長さを 30 文字以下に制限しています。この制限に合わせるために、 バックエンドは識別子名を切り詰めて、最後の 4 文字を MD5 のハッシュ値で置き 換えます。
Django は通常、 NULL ではなく空文字列を使うようにしていますが、 Oracle はこ
れらを別々のものとして扱います。この問題を回避するには、 Oracle バックエン
ドは空文字列を値として受け入れるフィールドに null=Ture
オプションを
強制的に付加します。データベースから値を取り出すとき、フィールドの値が NULL
であれば、そのフィールドの値は実際には空文字列であるとみなし、値も暗黙のう
ちに空文字列に変換されます。
TextField
への制限¶Oracle バックエンドは TextField
を NCLOB
カラム形式で保存します。
Oracle は、一般に LOB カラムに以下の制約を課しています:
- LOB カラムは主キーにできません。
- LOB カラムはインデクス化に使えません。
- LOB カラムは
SELECT DISTINCT
できません。従って、Oralce バックエン ドを使っていて、TextField
カラムを含むモデルに対してQuerySet.distinct
を行うとエラーを引き起こします。このエラーを避け るには、distinct()
クエリの対象モデルからTextField
を除去し、TextField
を持つ他のモデルを定義しておいてリレーションを張ってくだ さい。
In addition to the officially supported databases, there are backends provided by 3rd parties that allow you to use other databases with Django:
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.
Oct 26, 2017