sql >> データベース >  >> RDS >> PostgreSQL

データベースをPostgreSQLバージョン10にアップグレードする-知っておくべきこと

    PostgreSQL 11に関する投稿がウェブ上にますます表示されるにつれて、Postgres 9を使用するときに古くなったと感じるかもしれません。PostgreSQL10バージョンのリリースはほんの数か月前に行われただけですが、人々はすでに次のバージョンについて話し合っています。物事は動いているので、取り残されたくありません。このブログでは、最新バージョンのPostgres10にアップグレードするために知っておくべきことについて説明します。

    アップグレードオプション

    開始する前に最初に知っておくべきことは、アップグレードを行うにはいくつかの方法があるということです。

    1. 従来のpg_dumpall(pg_dump)/ pg_restore(psql)
    2. 従来のpg_upgrade
    3. トリガーベースのレプリケーション(Slony、自作)
    4. pglogicalレプリケーションの使用

    なんでこんなにバラエティがあるの?それぞれが異なる歴史を持っているので、セットアップして異なるサービスを提供するために異なる努力を必要とします。それぞれを詳しく見ていきましょう。

    従来のダンプ/復元

    pg_dump t > /tmp/f
    psql -p 5433 -f /tmp/f

    従来のダンプ/復元は完了するまでに最も長い時間がかかりますが、ダウンタイムを許容できる人にはよくある選択です。まず、論理バックアップを取り、それを新しい上位バージョンのデータベースに復元するのと同じくらい簡単です。データを「新しい構造」に「インポート」するので、実際にはアップグレードではないと言えます。その結果、2つのセットアップが作成されます。1つは古い(下位バージョン)、もう1つは新しくアップグレードされたものです。復元プロセスがエラーなしで終了した場合、あなたはほとんどそこにいます。そうでない場合は、既存の古いクラスターを変更してエラーを排除し、プロセスを最初からやり直す必要があります。

    インポートにpsqlを使用する場合は、移行前に新しいセットアップで実行するために、プリロードスクリプトを自分で作成する必要がある場合もあります。たとえば、pg_dumpall -gを使用して新しいセットアップで準備する必要のある役割のリストを取得するか、逆にpg_dump-xを実行して古いものからアクセス許可をスキップします。このプロセスは小さなデータベースでは非常に単純です。複雑さはdb構造のサイズと複雑さとともに増大し、セットアップした機能によって異なります。基本的に、この方法を成功させるには、アップグレードが成功するまで試行と修正を続ける必要があります。

    この方法を使用する利点は次のとおりです...

    • 作成した1つのバックアップで長い時間を費やす可能性がありますが、古いサーバーの負荷は1つのバックアップを取るのと同じくらい小さいです。
    • この方法は、ほとんどの場合、バックアップと復元のシーケンスにすぎません(一部のスペル、曲、ドラムを使用する可能性があります)
    • この方法を使用することは、アップグレードする最も古い方法であり、多くの人々によって検証されています

    最終的にアップグレードが完了したら、古いサーバーをシャットダウンするか、データの損失を受け入れる必要があります(または、新しいサーバーへのバックアップの復元中に古いサーバーで発生したDMLを再生します)。そして、それを行うのに費やされる時間は、データベースのサイズに比例します。

    もちろん、復元が完了する前に(特に、すべてのインデックスが作成される前に、新しいデータベースの「使用」を開始できます。多くの場合、最も時間がかかるのはインデックスです)。しかし、それにもかかわらず、そのようなダウンタイムはしばしば受け入れられません。

    従来のpg_upgrade

    MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/initdb -D tl0 >/tmp/suppressing_to_save_screen_space_read_it
    
    WARNING: enabling "trust" authentication for local connections
    You can change this by editing pg_hba.conf or using the option -A, or
    --auth-local and --auth-host, the next time you run initdb.
    MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/pg_upgrade -b /usr/local/Cellar/postgresql/9.5.3/bin -B /usr/local/Cellar/postgresql/10.2/bin -d t -D tl0 | tail
    Creating script to delete old cluster                        ok
    
    Upgrade Complete
    ----------------
    Optimizer statistics are not transferred by pg_upgrade so,
    once you start the new server, consider running:
        ./analyze_new_cluster.sh
    
    Running this script will delete the old cluster’s data files:
        ./delete_old_cluster.sh

    従来のpg_upgradeは、メジャーバージョンへのアップグレードにかかる時間を短縮するために作成されました。関係の量に応じて、特に--link引数を使用すると、数分(1つのテーブルデータベースのようなばかげた場合は秒、「反対の場合」は数時間)の速度になります。

    準備手順は、最初のアップグレード方法とは少し異なります。アップグレードをモックアップして、それが可能かどうかを確認するには、ストリーミングレプリケーションを構築するか、WALからスタンバイサーバーをリカバリする必要があります。なぜこれほど複雑なのですか?元の状態と同じように、as-close-in-state-databaseでアップグレードをテストする必要があります。ここでは、「バイナリ」レプリケーションまたはPITRが役立ちます。リカバリとrecovery_target_action=プロモート(PITR)または新しくビルドされたスレーブのプロモート(pg_ctlプロモートまたはトリガーファイルの配置)(ストリーミングレプリケーション)が完了したら、pg_upgradeの実行を試みることができます。 pg_upgrade_internal.logを確認すると、プロセスが成功したかどうかがわかります。さらに、前の方法と同じ試行錯誤のアプローチがあります。 pg_upgradeが正常に実行されるまで、テストデータベースに対して実行されたアクションをスクリプトに保存します。さらに、不要になったテストを破棄できます アップグレードされたデータベース、次に保存されたスクリプトを実行して、アップグレードを実行するための元のデータベースを準備します。

    この方法を使用する利点は次のとおりです…

    • 論理バックアップ/復元よりも短いダウンタイム
    • きちんとしたプロセス-pg_upgradeは、元のデータベースを既存のデータと構造でアップグレードします
    • 過去に多く使用されてきましたが、9.4未満のバージョンを実行しているほとんどのDBA(pglogicalの使用を許可)の優先事項になります

    この方法を使用することの欠点は次のとおりです…

    • ダウンタイムが必要です

    トリガーベースのレプリケーション

    バージョン10がポート5433にあり、同じテーブルが用意されていると仮定します。

    db=# create server upgrade_to_10 foreign data wrapper postgres_fdw options (port '5433', dbname 'dbl0');
    CREATE SERVER
    Time: 9.135 ms
    db=# create user mapping for vao SERVER upgrade_to_10 options (user 'vao');
    CREATE USER MAPPING
    Time: 8.741 ms
    db=# create foreign table rl0 (pk int, t text) server upgrade_to_10 options (table_name 'r');
    CREATE FOREIGN TABLE
    Time: 9.358 ms

    これは非常に単純なfn()であり、非常に基本的な論理レプリケーションのトリガーです。このようなアプローチは非常に原始的であるため、外部キーでは機能しませんが、コードは短いです:

    db=# create or replace function tf() returns trigger as $$
    begin
     if TG_0P = 'INSERT' then
       insert into r10 select NEW.*;
     elseif TG_0P = 'UPDATE' then
       delete from rl0 where pk = NEW.pk;
       insert into rl0 select NEW.*;
     elseif TG_0P = 'DELETE' then
       delete from rl0 where pk = OLD.pk;
     end if;
    return case when TG_0P in ('INSERT','UPDATE') then NEW else OLD end;
    end;
    SS language plpgsql;
    CREATE FUNCTION
    Time: 8.531 ms
    db=# create trigger t before insert or update or delete on r for each row execute procedure tf(); CREATE TRIGGER
    Time: 8.813 ms

    例:

    db=# insert into r(t) select chr(g) from generate_series(70,75) g;
    INSERT 0 6
    Time: 12.621 ms
    db=# update r set t = 'updated' where pk=2;
    UPDATE 1
    Time: 10.398 ms
    db=# delete from r where pk=1;
    DELETE 1
    Time: 9.634 ms
    db=# select * from r;
     pk |    t
    ----+---------
      3 | H
      4 | I
      5 | J
      6 | K
      2 | updated
    (5 rows)
    
    Time: 9.026 ms
    db=# select * from rl0;
     pk |    t
    ----+---------
      3 | H
      4 | I
      5 | J
      6 | K
      2 | updated
    (5 rows)
    
    Time: 1.201 ms

    最後に、別のデータベースに複製することを確認します。

    db=# select *,current_setting('port') from dblink('upgrade.to.lO','select setting from pg_settings where name=$$port$$') as t(setting_10 text);
     setting_10 | currerrt.setting
    ------------+------------------
     5433       | 5432
    (l row)
    
    Time: 23.633 ms

    私はこの方法を最もエキゾチックと呼ぶでしょう。ストリーミングレプリケーションとその後のpglogicalの両方で、トリガーベースのレプリケーションの使用はあまり一般的ではなくなります。マスターへの負荷が高く、セットアップ中の複雑さが増し、適切に構造化されたドキュメントが不足しています。さまざまなメジャーバージョンでSlonyをセットアップしたいだけなので、ここではプロセスの準備はありません。

    この方法を使用する利点は次のとおりです…

    • バックアップを取る必要はなく、ダウンタイムも必要ありません(特に、pgbouncerまたはhaproxyの背後にいます)。

    この方法を使用することの欠点は次のとおりです…

    • セットアップの複雑さの高さ
    • 構造化されたドキュメントの欠如
    • あまり人気がない-調査(および共有)するユーザーケースが少ない

    同じように、自己作成のトリガーレプリケーションはアップグレードのもう1つの可能な方法です。考え方は同じですが(新しい上位バージョンのデータベースを起動し、下位バージョンにトリガーを設定して変更されたデータをデータベースに送信します)、自己作成の設定は明確になります。サポートは必要ないため、実行時に使用するリソースが少なくなる可能性があります。もちろん、同じ理由で、いくつかの機能が欠落しているか、期待どおりに機能していない可能性があります。新しいバージョンに移行するテーブルが複数ある場合、そのようなオプションを使用すると、おそらく時間がかからず、うまく行けば、リソースの消費が少なくなる可能性があります。ボーナスとして、いくつかのETL変換をアップグレードと組み合わせて、ダウンタイムなしで新しいバージョンに切り替えることができます。

    今日のホワイトペーパーをダウンロードするClusterControlを使用したPostgreSQLの管理と自動化PostgreSQLの導入、監視、管理、スケーリングを行うために知っておくべきことについて学ぶホワイトペーパーをダウンロードする

    pglogicalを使用した論理レプリケーション

    これは、Postgresをアップグレードするための非常に有望な新しい方法です。アイデアは、異なるメジャーバージョン間で論理レプリケーションを設定し、文字通り、同じデータを実行する並列の上位(または下位)バージョンのデータベースを持つことです。準備ができたら、アプリケーションとの接続を古いものから新しいものに切り替えるだけです。

    この方法を使用する利点は次のとおりです…

    • 基本的にダウンタイムなし
    • 非常に有望な機能であり、トリガーベースのレプリケーションよりもはるかに少ない労力です

    この方法を使用することの欠点は次のとおりです…

    • セットアップはまだ非常に複雑です(特に古いバージョンの場合)
    • 構造化されたドキュメントの欠如
    • あまり人気がない-調査(および共有)するユーザーケースが少ない

    トリガーベースとpglogicalレプリケーションの両方のメジャーバージョンの移行を使用して、バージョンをダウングレードできます(たとえば、pglogicalは9.4からのみ使用可能であり、トリガーレプリケーションは、必要なバージョンとしてセットアップするのがますます難しくなります。ダウングレードして古くなります。

    アップグレード前に実行するアクション

    • バックアップを取る
    • 十分なディスク容量があることを確認してください
    • 拡張機能を確認します(外部モジュールもバイナリ互換であることが重要ですが、pg_upgradeでは確認できません)
    • 新しいデータベースで同じdatcollat​​eとdatctypeなどを使用するようにしてください(pg_databaseを確認してください)
    • アップグレードを中断する可能性のあるビュー、関数、拡張機能、タイプをチェック(DDL +ドロップ)
    • 実際にpg_upgradeの前に--checkを使用します

    アップグレード後に実行するアクション

    • pg_upgrade_server.logを参照してください(pg_upgradeを使用した場合)
    • アップグレードされたデータベースでanalyzeを実行します(autovacuumで実行されるため、オプションですが、自分で行う場合は、最初に分析する関係を選択できます)
    • 人気のあるページを予熱します(オプションですが、最初はパフォーマンスを向上させる可能性があります)

    結論

    PostgreSQLバージョン10に移行する前に知っておくと便利な一般的な注意事項を次に示します…

    • pg_sequencesが導入され、以前は人気のあったSELECT *FROMsequence_nameの動作が変更されました。 log_cnt | is_calledが返され、「初期プロパティ」が非表示になります(変更された動作に依存するコードを調整します)
    • pg_basebackupはデフォルトでWALをストリーミングします。アップグレード後、スクリプトを変更する必要がある場合があります(オプション-xは削除されました)
    • すべてのpg_ctlアクションは完了を待っています。以前は、pg_ctlの開始直後にデータベースに接続しようとしないように、-wを追加する必要がありました。したがって、「非同期」の開始または停止を引き続き使用する場合は、明示的に-Wでマークする必要があります。スクリプトが意図したとおりに動作するように、スクリプトを調整する必要がある場合があります。
    • WALをアーカイブしたり、ストリーミングレプリケーションまたはPITRを監視/制御したりするためのすべてのスクリプトを確認して、変更されたxlog名に合わせて調整する必要があります。例えば。 select * from pg_is_xlog_replay_paused()は、スレーブWALの再生の状態を表示しなくなりました。代わりにselect * from pg_is_wal_replay_paused()を使用する必要があります。また、cp / blah / pg_xlog/*は/blah/ pg_wal / *などに変更する必要があります。これは、基本的にpg_xlogのすべてのオカレンスに対して行われます。このような大規模な下位互換性のない変更の背後にある理由は、newbyがログ先行書き込みを削除してログを削除することで「スペースをクリーンアップ」し、データベースを失う場合に対処するためです。
    • 新しい名前のpg_stat_replicationを使用してスクリプトを調整します(場所はlsnに変更されました)
    • 必要に応じて、戻り関数を設定してクエリを調整します
    • バージョン10より前の拡張機能としてpglogicalを使用した場合は、「列」間で値を変更するpg_hba.confを調整する必要がある場合があります
    • ログであるpg_logの新しい名前のスクリプトを調整します。たとえば、find / pg_data / pg_log / postgresql- * -mmin + $((60 * 48))-type f -exec bash /blah/moveto.s3 .sh {} \;動作します。もちろん、代わりにシンボリックリンクを作成することもできますが、デフォルトの場所でログを見つけるためにアクションを実行する必要があります。デフォルトのもう1つの小さな変更は、log_line_prefixです。正規表現が特定の形式に依存している場合は、それを調整する必要があります。
    • Postgresデータベースで暗号化されていないパスワードをまだ使用していた場合、このリリースではパスワードが完全に削除されます。それで、-暗号化されていない...
    • に依存した人々のために物事を整理する時が来ました。
    • 以前のリリースとの互換性のない残りの変更は、多くのコードで参照するには新鮮すぎる(min_parallel_relation_size)か、古すぎる(外部tsearch2)か、エキゾチックすぎる(ビルドでの浮動小数点タイムスタンプの削除サポート)ためです。それらをスキップします。もちろん、それらはリリースページにリストされています。
    • 9.5から9.6の場合と同様に、pg_stat_activity(1つの新しい列と新しい可能な値)をクエリするためにスクリプトを調整する必要がある場合があります。
    • バキューム冗長出力を保存/分析している場合は、コードを調整する必要があるかもしれません
    • また、新しいパーティショニングの実装を確認することもできます。既存の「セット」をリファクタリングして、新しい「標準」に準拠することもできます。
    • タイムラインを確認します(pg_upgradeを実行すると、新しいデータベース用にリセットされます)

    10にアップグレードするために知っておく必要のあるこれらの手順とは別に、このリリースを非常に期待されているものにする多くのことがあります。リリースノートまたはdepeszブログの変更に関するセクションをお読みください。


    1. ORA-00932:データ型に一貫性がありません:予期されました-CLOBを取得しました

    2. mycliを使用して、ターミナルでMariaDB/MySQLを快適に学習してください。

    3. PostgreSQL10でのICUサポートとのより堅牢な照合

    4. Oracle CloudPlatformでのMySQLデータベースサービスでのOracleJDeveloperの使用、パート3