web-dev-qa-db-ja.com

稼働中の本番データベースのテーブルを変更する

ほとんどの "人気のある"(MySQL、Postgres ...)データベースシステムは、ライブプロダクションデータベースのテーブルの変更(列のタイプの追加、削除、変更など)をどのように処理しますか?

私は正しい方法がスケジュールされたすべてのダウンタイムをバックアップしてから変更を行うことを知っています.

しかし...現在のデータベースシステムは、これらを「オンライン」で何も停止せずに実行することをサポートしていますか? (変更/削除されている列を参照するクエリを遅らせるだけかもしれません)

そして、私がALTER TABLE...稼働中のデータベースで?これが起こるとすべてが停止しますか?データが破損することはありますか?等.

繰り返しますが、私はPostgresまたはMySQLを主に言及しています。

(そして、はい、「正しい方法」を行う前にこれを行う必要があったときはいつでも、バックアップ、ダウンタインのスケジューリングなど...しかし、この種のことや「クイックダーティ」、または「クイック、ライブ、ダーティ」スキーマ変更を実際にサポートするDBシステムがある場合)


誰かが提案した FacebookスクリプトからのMySQLのオンラインスキーマの変更 (チュートリアル here およびソース here を使用)... 「ハッキー」な一連の方法を自動化します...制作に似た何かで誰かがこれを使用したことがありますか?

26
NeuronQ

PostgreSQLでALTER TABLEを発行すると SELECTを含むすべてをブロックするACCESS EXCLUSIVEロックがかかります 。ただし、テーブルが再書き込みを必要とせず、新しいUNIQUECHECK、またはFOREIGN KEY制約が検証のために高価な全テーブルスキャンを必要としない場合など、このロックは非常に簡単です。

疑わしい場合は、一般的にそれを試すことができます! PostgreSQLのすべてのDDLはトランザクション対応であるため、時間がかかりすぎて他のクエリを保留し始めた場合は、ALTER TABLEをキャンセルしても問題ありません。さまざまなコマンドに必要なロックレベルは ロックページに記載 です。

通常は遅い操作の一部は、ダウンタイムなしで安全に実行できるように高速化できます。たとえば、テーブルtがあり、列customercode integer NOT NULLtextに変更する場合、顧客はすべての顧客コードをXで始める必要があると判断したため、次のように記述できます。

ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );

...しかし、それは再書き込みのためにテーブル全体をロックします。同様に、DEFAULTを使用して列を追加します。これは、長いロックを回避するためにいくつかのステップで実行できますが、アプリケーションは一時的な複製に対処できなければなりません。

ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;

これは、プロセス中にwritestに変換されるのを防ぐだけです。ロック名EXCLUSIVEは、すべてを除外するという点で多少誤解を招きますSELECTを除く; ACCESS EXCLUSIVEモードは、すべてを完全に排除する唯一のモードです。 ロックモード を参照してください。 ALTER TABLEが必要とするロックのアップグレードが原因で、この操作がデッドロックロールバックする可能性がありますが、最悪の場合、もう一度実行する必要があります。

tまたはINSERTが着信するたびに、UPDATEからcustomercode_newに自動的に入力されるcustomercodeでトリガー関数を作成することにより、そのロックを回避してすべてをライブで行うこともできます。

CREATE INDEX CONCURRENTLYALTER TABLE ... ADD table_constraint_using_index のような組み込みツールもあり、DBAがよりゆっくりと作業を行うことで排他ロック期間を短縮できるように設計されています並行性に配慮した方法で。

pg_reorg ツールまたはその後継ツール pg_repack は、一部のテーブル再構築操作にも使用できます。

22
Craig Ringer

Perconaは、オンラインスキーマ変更を実行するための独自のツールを開発しました

ツールは pt-online-schema-change と呼ばれます

これにはトリガーが含まれるため、ドキュメントをよくお読みください。

ドキュメントによると、行われる主な操作は

  • 健全性チェック
  • チャンキング
  • オンラインスキーマ変更
    • 一時テーブルを作成および変更する
    • テーブルから一時テーブルへの変更をキャプチャする
    • テーブルから一時テーブルに行をコピーする
    • テーブルと一時テーブルを同期します
    • テーブルと一時テーブルを入れ替える/名前を変更する
    • 掃除
7
RolandoMySQLDBA

システムをシャットダウンしてすべての変更を一度に行うことは非常に危険な場合があります。何かがうまくいかず、頻繁にそれが起こった場合、簡単に戻る方法はありません。

アジャイル開発者として、テーブルが変更されて読み取られるため、ダウンタイムなしでテーブルをリファクタリングする必要がある場合があります。

次のアプローチは、ロールバックが非常に簡単ないくつかの低リスクのステップで変更が行われるため、低リスクです。

  • テーブルにアクセスするすべてのモジュールが自動テストで十分にカバーされていることを確認してください。
  • 新しいテーブルを作成します。古いテーブルを変更するすべてのプロシージャを変更して、古いテーブルと新しいテーブルの両方を変更するようにします。
  • 既存のデータを新しい構造に移行します。サーバーの全体的なパフォーマンスに深刻な影響を与えないように、小さめのバッチで実行してください。
  • データの移行が成功したことを確認します。
  • 古いテーブルから新しいテーブルにいくつかの選択手順をリダイレクトします。自動テストを使用して、変更されたモジュールがまだ正しいことを確認します。それらのパフォーマンスが許容範囲内であることを確認してください。変更したプロシージャを展開します。
  • すべてのレポートが新しいテーブルを使用するまで、前の手順を繰り返します。
  • 新しいテーブルにのみアクセスできるように、テーブルを変更するプロシージャを変更します。
  • 古いテーブルをアーカイブして、システムから削除します。

このアプローチを何度も使用して、ダウンタイムなしで大きなライブプロダクションテーブルを変更しました。まったく問題はありません。

6
A-K

はい、多くの最新のデータベースでは、列を追加したり、null許容値の追加や削除など、列の特性を変更したりできます。

列を削除すると、データは失われますが、破損の恐れはあまりありません。

2
Marlin Pierce

Perconaツールは、トリガーを使用して変更を支援します。テーブルに既存のトリガーがすでにある場合は、うまく機能しません。データベースにとって非常に重要であるため、既存のトリガーを実際に処理するものを作成する必要がありました https://github.com/StirlingMarketingGroup/smg-live-alter

0
Brian Leishman