Manual:スキーマの変更
このページは開発作業の一部としてデータベースのレイアウトを変更する必要がある人々のために、MediaWiki コアとその拡張機能のためのスキーマ変更パッチを構築する方法を説明するヘルプ ページです。
用語集
- スキーマ - MediaWiki の現在のデータベース レイアウト。
- スキーマの変更 - スキーマ移行のアトミックな部分で、コミットによって追加されるもの。 例えば、「テーブル foo を追加」、「テーブル baz からカラム bar を削除」などです。
- データベース管理システム (DBMS) - MediaWiki のデータベースを扱う基盤技術。 MediaWiki コアでサポートされているものは以下の通りです: MySQL、SQLite、PostgreSQL。 拡張機能を使用するとより多くなる可能性があります。
- データ定義言語 (DDL) - スキーマやスキーマ変更を定義する構文 (DBMS によって異なる場合がある)。 例: 「ALTER TABLE」「DROP COLUMN」。 「.sql」ファイルとして保存されます。
- データベース抽象レイヤー (DBAL) - DBMS に依存しないデータベース スキーマおよびスキーマ変更定義と実際の DDL との間の橋渡し。
概要
各スキーマの変更では、2 つの部分を処理する必要があります。 第一に、新しいインストレーションは古いスキーマではなく新しいスキーマを持つ必要があり、第二に、古いインストレーションは新しいスキーマにアップグレードできる必要があります。 最初のパートでは、スキーマ DDL ファイル (tables.sql という名前で保存) を修正し、2 番目のパートでは、「ALTER TABLE」パッチを提供し、それをアップデーターのロジックに配線します。
DBMS ごとに 1 つずつある専用 DDL を、1 つの抽象スキーマに移行している真っ最中です。 テーブルによっては、複数の生の SQL ファイルを変更したり、1 つの json ファイルのみを変更し、メンテナンス スクリプトを使用して SQL ファイルを生成することがあります。
手動 (廃止予定)
2020年まで使用されるこの方式では、スキーマを変更する際に:
- 2 か所にある tables.sql を変更 (MySQL は maintenance/tables.sql、PostgreSQL は maintenance/postgres/tables.sql)
- MySQL の現行インストレーションのアップグレード パスとして、スキーマ変更 DDL ファイルを作成し、maintenance/archives/ に配置します
- 他の種類の DBMS でそのパッチが動作しない場合は、専用のパッチを作成する必要があります。 例えば、SQLite には ALTER TABLE がありません。つまり、一時テーブルを作成してデータをコピーし、古いテーブルを削除して、新しいテーブルの名前を古い名前に変更する必要があるのです。 例
- これらの DDL ファイル (ステップ 2 より) を MysqlUpdater, SqliteUpdater, PostgresUpdater に配線します
例
自動的な生成
MediaWiki バージョン: | ≧ 1.35 |
MediaWiki コアのすべてのテーブルの抽象スキーマは「sql/tables.json」にあります。 この抽象化では、Doctrine DBAL ライブラリを使用して DDL ファイルを生成しています。 On your local working MediaWiki install, with the relevant extension installed, you should:
- tables.json 構造を変更します。
- メンテナンス スクリプトを実行し、3 つの DDL ファイルを生成します:
php maintenance/run.php generateSchemaSql.php --json sql/tables.json --sql sql/ --type=all
- 抽象スキーマ変更の .json ファイル (下記を参照) を作成し、sql/abstractSchemaChanges/ ディレクトリに配置します
- メンテナンス スクリプトを使用してスキーマ パッチを構築します。例:
php maintenance/run.php generateSchemaChangeSql.php --json sql/abstractSchemaChanges/patch-logging-rename-indexes.json --sql sql/ --type=all
- MysqlUpdater, SqliteUpdater, PostgresUpdater に追加します
- パッチを作成する際には、変更点と自動生成された DDL ファイルを git でチェックアウトすることを忘れないでください。
パッチの例
抽象スキーマの例
[
{
"name": "actor",
"comment": "The \"actor\" table associates user names or IP addresses with integers for the benefit of other tables that need to refer to either logged-in or logged-out users. If something can only ever be done by logged-in users, it can refer to the user table directly.",
"columns": [
{
"name": "actor_id",
"comment": "Unique ID to identify each actor",
"type": "bigint",
"options": { "unsigned": true, "notnull": true, "autoincrement": true }
},
{
"name": "actor_user",
"comment": "Key to user.user_id, or NULL for anonymous edits",
"type": "integer",
"options": { "unsigned": true, "notnull": false }
},
{
"name": "actor_name",
"comment": "Text username or IP address",
"type": "binary",
"options": { "length": 255, "notnull": true }
}
],
"indexes": [
{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
],
"pk": [ "actor_id" ]
}
]
注記
- Doctrine DBAL の既定値は
"notnull": true
です。 null 可能 (nullable) にしたい場合は、"notnull": false
で明示的に指定します。 - Doctrine DBAL のカラム型の一覧はこちらにあります: https://github.com/doctrine/dbal/blob/3.3.8/src/Types/Types.php
- Since MediaWiki 1.38, Doctrine DBAL types which are not listed in the following table are unavailable.
Doctrine DBAL/抽象スキーマ | MySQL | SQLite | PostgreSQL | Version | |
---|---|---|---|---|---|
bigint | BIGINT | BIGINT | BIGSERIAL (自動インクリメントの場合)/BIGINT | ||
binary | VARBINARY | BLOB | TEXT | ||
blob | TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB (サイズに基づく) | BLOB | TEXT | ||
datetimetz | DATETIME | DATETIME | TIMESTAMPTZ (1.36+) TIMESTAMP(0) WITH TIME ZONE (1.35) |
||
float | FLOAT/DOUBLE PRECISION (if "doublePrecision":true ) (1.36+)DOUBLE PRECISION (1.35) |
DOUBLE PRECISION | FLOAT/DOUBLE PRECISION (if "doublePrecision":true ) (1.36+)DOUBLE PRECISION (1.35) |
||
integer | INT | INTEGER | INT | ||
smallint | SMALLINT | SMALLINT | SMALLINT | ||
string | VARCHAR | VARCHAR | VARCHAR | ||
text | TINYTEXT/TEXT/MEDIUMTEXT/LONGTEXT (サイズに基づく) | CLOB | TEXT | ||
mwenum | ENUM | TEXT | TEXT |
| |
mwtimestamp | BINARY(14)/VARBINARY(14) (if "allowInfinite":true )
|
BLOB | TIMESTAMPTZ |
| |
mwtinyint | TINYINT | SMALLINT | SMALLINT |
|
抽象スキーマの変更
スキーマの変更については、テーブルの抽象スキーマの変更前と変更後のスナップショットを json ファイルで作成します (1 テーブルにつき 1 つのスキーマ変更でお願いします)。 その後、同様の方法でメンテナンス スクリプトを実行すると、2 つのテーブル間の差分を取り、スキーマ変更用の DDL ファイルを自動生成します。
抽象スキーマの変更の例
{
"before": {
"name": "actor",
"columns": [
{
"name": "actor_id",
"type": "bigint",
"options": { "unsigned": true, "notnull": true, "autoincrement": true }
},
{
"name": "actor_user",
"type": "integer",
"options": { "unsigned": true, "notnull": false }
},
{
"name": "actor_name",
"type": "binary",
"options": { "length": 255, "notnull": true }
}
],
"indexes": [
{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
],
"pk": [ "actor_id" ]
},
"after": {
"name": "actor",
"columns": [
{
"name": "actor_id",
"type": "bigint",
"options": { "unsigned": true, "notnull": true, "autoincrement": true }
},
{
"name": "actor_user",
"type": "bigint",
"options": { "unsigned": true, "notnull": false }
},
{
"name": "actor_name",
"type": "binary",
"options": { "length": 255, "notnull": true }
}
],
"indexes": [
{ "name": "actor_user", "columns": [ "actor_user" ], "unique": true },
{ "name": "actor_name", "columns": [ "actor_name" ], "unique": true }
],
"pk": [ "actor_id" ]
}
}
2 つのテーブルは、「actor_user」の型が「integer」から「bigint」に変更されている点を除いて同じです。 変更自体を抽象化するのではなく差分を取る理由は、SQLite はほとんどの場合 ALTER TABLE を持っておらず、つまり DBAL は一時テーブルを使ってスキーマ変更 DDL ファイルを構築するためにスキーマを知る必要があるからです。
Best practices in choosing the data type
- For timestamps, use mwtimestamp datatype (phab:T42626).
- Instead of VARCHAR or CHAR, use VARBINARY or BINARY (otherwise you have to deal with encodings in databases)
- Unless you actually need the negative value, use UNSIGNED for any type of integer value to double its capacity.
- Using ENUM is highly discouraged (phab:T119173).