Manual:スキーマの変更

This page is a translated version of the page Manual:Schema changes and the translation is 89% complete.

このページは開発作業の一部としてデータベースのレイアウトを変更する必要がある人々のために、MediaWiki コアとその拡張機能のためのスキーマ変更パッチを構築する方法を説明するヘルプ ページです。

用語集

  • スキーマ - MediaWiki の現在のデータベース レイアウト
  • スキーマの変更 - スキーマ移行のアトミックな部分で、コミットによって追加されるもの。 例えば、「テーブル foo を追加」、「テーブル baz からカラム bar を削除」などです。
  • データベース管理システム (DBMS) - MediaWiki のデータベースを扱う基盤技術。 MediaWiki コアでサポートされているものは以下の通りです: MySQLSQLitePostgreSQL。 拡張機能を使用するとより多くなる可能性があります。
  • データ定義言語 (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 ファイルを生成することがあります。

手動 (廃止予定)

メインのページ: Manual:SQL patch file

2020年まで使用されるこの方式では、スキーマを変更する際に:

  1. 2 か所にある tables.sql を変更 (MySQL は maintenance/tables.sql、PostgreSQL は maintenance/postgres/tables.sql)
  2. MySQL の現行インストレーションのアップグレード パスとして、スキーマ変更 DDL ファイルを作成し、maintenance/archives/ に配置します
    • 他の種類の DBMS でそのパッチが動作しない場合は、専用のパッチを作成する必要があります。 例えば、SQLite には ALTER TABLE がありません。つまり、一時テーブルを作成してデータをコピーし、古いテーブルを削除して、新しいテーブルの名前を古い名前に変更する必要があるのです。
  3. これらの 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:

  1. tables.json 構造を変更します。
  2. メンテナンス スクリプトを実行し、3 つの DDL ファイルを生成します:
    php maintenance/run.php generateSchemaSql.php --json sql/tables.json --sql sql/ --type=all
    
  3. 抽象スキーマ変更の .json ファイル (下記を参照) を作成し、sql/abstractSchemaChanges/ ディレクトリに配置します
  4. メンテナンス スクリプトを使用してスキーマ パッチを構築します。例:
    php maintenance/run.php generateSchemaChangeSql.php --json sql/abstractSchemaChanges/patch-logging-rename-indexes.json --sql sql/ --type=all
    
  5. MysqlUpdater, SqliteUpdater, PostgresUpdater に追加します
  6. パッチを作成する際には、変更点と自動生成された 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 型とそれらと同等の型
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
1.36
mwtimestamp BINARY(14)/VARBINARY(14) (if "allowInfinite":true) BLOB TIMESTAMPTZ
1.36
mwtinyint TINYINT SMALLINT SMALLINT
1.36


抽象スキーマの変更

スキーマの変更については、テーブルの抽象スキーマの変更前と変更後のスナップショットを 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).