質問

Postgres にスキーマがあるので、スキーマ パッチを適用する適切な方法を確立したいと考えています。

現在、スキーマ、テーブル、シーケンス、関数などを作成する一連の DDL ファイルがあります。テスト環境用の作成スクリプトもあります。これらのファイルはすべて、開発やテストなどのためにデータベース環境を再作成するために使用されます。

システムのバージョンに対応する「パッチ」ファイルも多数あります。つまり。patches/1.0.0.sql、patches/1.0.1.sql などこれらのファイルは、ステージング データベースと運用データベースを更新するために使用されます。

このプロセスは今のところ機能していますが、スキーマに最適なパッチを適用する方法について社内で議論がありました。

ステージングおよび運用スキーマにパッチを適用するプロセスとして、他の人がどのようなプロセスを行っているのか、またデータベースのバージョンを管理する方法に興味があります。

ありがとう!

役に立ちましたか?

解決

仕事では、SQL Server の場合、最初に行われる変更をロールバックするスキーマ変更スクリプトを作成します (つまり、スキーマ変更がまだ適用されていない場合でもロールバック セクションは正常に実行されるように冪等)、次に変更を適用するセクションを作成します。 。TSQL では、システム カタログや他のテーブルを覗いて、テーブル/列/インデックス/行が既に存在するかどうかを確認し、存在しない場合は何も実行するのは簡単です。

PostgreSQL では、サーバーに送信できるコマンドにはもう少し制約があります。ただし、DDL はトランザクションであるため、中途半端に適用されたスキーマ変更は発生しません。私は仕事で慣れているスキームを自分の小さなプロジェクトにうまく応用しました(やりすぎ?ただし、ここでも開発/テスト データベースと「実際の」データベースがあります)。たとえば、次のようになります。

\echo Rolling back schema change #35

BEGIN;

DELETE FROM schema_version WHERE schema_id = 35;

DROP TABLE IF EXISTS location_coordinates;
DROP FUNCTION IF EXISTS location_coordinates_populate();

END;

\echo Applying schema change #35

BEGIN;

INSERT INTO schema_version(schema_id, description) VALUES(35, 'Add location_coordinates table');

CREATE TABLE location_coordinates(
 location_id INT PRIMARY KEY REFERENCES location(location_id),
 latitude FLOAT NOT NULL,
 longitude FLOAT NOT NULL,
 earth_coordinates earth NOT NULL,
 box_10miles cube NOT NULL
);

GRANT SELECT, INSERT, UPDATE, DELETE ON location_coordinates TO ui;

CREATE FUNCTION location_coordinates_populate() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$
BEGIN
  new.earth_coordinates := ll_to_earth(new.latitude, new.longitude);
  new.box_10miles := earth_box(new.earth_coordinates, 10 * 1609.344);
  RETURN new;
END
$$;

CREATE TRIGGER location_coordinates_populate BEFORE INSERT OR UPDATE ON location_coordinates
 FOR EACH ROW EXECUTE PROCEDURE location_coordinates_populate();

INSERT INTO location_coordinates(location_id, latitude, longitude)
 SELECT location_id, latitude, longitude FROM location WHERE latitude IS NOT NULL AND longitude IS NOT NULL;

CREATE INDEX location_coordinates_10miles ON location_coordinates USING gist (box_10miles);

END;

\echo Done

このスクリプトは、「psql -f schema-changes/35.sql」だけでデータベース上で実行できます。「適用中...」メッセージまでを切り取るだけで、ロールバックするコマンドを取得できます。ご覧のとおり、変更によりメタデータ テーブル「schema_version」が維持されるため、どの変更が適用されたかを確認できます。変更全体は、トランザクション、データ移行などすべてとして実行されます。ここでは、DROP コマンドの「IF EXISTS」機能を使用して、変更が適用されていない場合でもロールバック セクションを正常に実行できるようにしました。私たちが Oracle の仕事で行ったことの 1 つは、スキーマの変更を PL/SQL として記述することでした。おそらく、変更を行うのに役立ついくつかの関数を plpgsql に含めることができるでしょうか。

上記の変更では、「緯度」列と「経度」列(NULL 可能)を「位置」から別の「位置座標」リレーションに移行しています(そして地球距離の要素を追加しています)。古い列を削除しないでください。注意しなければならないことの 1 つは、可能であればスキーマの変更に下位互換性を持たせることです。したがって、このスキーマ変更を適用できます 前に 新しいテーブルを使用するようにアプリを更新します。古い列を削除して適用する 2 番目の変更が必要です アプリを更新しています。職場では、これらは 2 つの異なるリリース サイクルで行われるため、リリース X では、最初にすべてのスキーマ変更をロールバックしなくても、アプリをリリース X-1 にロールバックするオプションがまだあります。また、アプリの前に別のウィンドウでスキーマの変更をデプロイすることもできます。(技術的には、古いテーブルへの更新が新しいテーブルに同期されるようにトリガーを作成する必要がありましたが、あまりにも仕事に似ているため、書きませんでした:))

また、すべてのデータベースをスパイダーして、その内容を確認するアプリケーションのようなものもあります。 schema_version テーブルを作成し、変更を追跡するため、接続しなくてもどのような変更が行われたのかを確認したり、各変更の履歴を把握したりすることもできます (「開発でロールバック」、「開発で適用」などを追跡します)。作業では、schema_version テーブルには著者情報なども含まれています。バージョン管理からバージョン情報を適用する魔法の方法は素晴らしいでしょう。私たちが抱えている問題の 1 つは、たとえば SC が QA で適用されてから Perforce で変更された場合、おそらく誰も気付かないことです。したがって、スキーマ変更 35 リビジョン #4 が適用されたことを追跡する方法があれば良いでしょう。

注意すべき点が 1 つあります。スキーマの変更には、アプリケーションのバージョンとは関係なく番号が付けられます。明らかにそれらは関連しています -- それはスパイダー アプリがユーザーに入力を許可するもう 1 つのことです -- しかし、私たちは「リリース X のすべてがここにあります」という巨大なパッチではなく、多くの小さな変更を加えようとしています。スキーマの変更は、新しいインデックスの追加などにも使用されるため、アプリ主導型ではない可能性があります。一般に、スキーマ変更は DBA ではなく開発者によって「所有」されます。ただし、上記の「インデックスの作成」の例では、DBA は基本的に開発者の役割を果たし、スキーマ変更を所有します。はい、私たちは開発者に高いレベルの SQL 能力を要求します。ただし、社内の他のグループは少し異なる働き方をしており、DB チームにより多くの仕事を与えています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top