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

オンラインアップグレードの進捗状況

    ここ数か月、AXLEプロジェクトの一環として、非常に大規模なデータベースのオンラインアップグレードに取り組んできました。このトピックについての考えと、最近の進捗状況を共有したいと思います。

    2ndQuadrantに参加する前、私はSkypeで働いていましたが、ビジネスではデータベースのメンテナンスウィンドウが許可されていませんでした。これは、展開やアップグレードなどのダウンタイムが許可されていないことを意味します。この種のルールにより、作業方法を変更できます。ほとんどの変更は小さく、重いロックは行わず、高速フェイルオーバーを可能にするレプリカがあります。ただし、リリースを小さくしてブロックしないようにすることはできますが、PostgreSQLデータベースのメジャーバージョンアップグレードを行う必要がある場合はどうなりますか?

    ほとんどの企業にはアップグレードウィンドウがあるため、別の状況にある可能性があります。そのため、アップグレード中にダウンタイムが発生する可能性があります。ただし、これには2つの問題があります。一つには、たとえ許可されていても、実際にダウンタイムを好む企業はありません。さらに重要なことに、データベースのサイズがギガバイトを超えてテラバイトまたは数百テラバイトの範囲に拡大すると、ダウンタイムに数日または数週間かかる可能性があり、その間、誰も操作を停止する余裕がありません。その結果、多くの企業は重要なアップグレードをスキップすることが多く、次のアップグレードは実際にはさらに苦痛になります。そして、開発者は新機能、パフォーマンスの改善を欠いています。彼ら(企業)は、サポートされなくなり、データの破損やセキュリティの問題がわかっているPostgreSQLバージョンを実行するリスクさえあります。次の段落では、アップグレードにかかる時間を短縮し、その結果、苦痛を軽減し、できればより頻繁にするための私の作業について少し説明します。

    まず、少し歴史から始めましょう。 PostgreSQL 9.0より前は、メジャーバージョンのアップグレードを行う唯一の方法は、pg_dumpを実行し、新しいバージョンのPostgreSQLを実行しているインスタンスにダンプを復元することでした。この方法では、構造とすべてのデータをデータベースから読み取り、ファイルに書き込む必要がありました。次に、ファイルから読み取り、新しいデータベースに挿入します。インデックスを再構築する必要があります。

    ご想像のとおり、このプロセスにはかなりの時間がかかる場合があります。パフォーマンスの改善は、実行する並列ジョブの数を指定できる-jオプションが追加されたpg_restoreの8.4で行われました。これにより、複数のテーブル(インデックスなど)を並行して復元できるようになり、カスタム形式のダンプの復元プロセスが高速化されます。 9.3バージョンでは、pg_dumpに同様のオプションが追加され、パフォーマンスがさらに向上しました。しかし、データ量が急速に増加していることを考えると、並列化自体では、アップグレードに必要な時間を大幅に増やすには不十分です。

    その後、PostgreSQL 9.0では、pg_upgradeというユーティリティが登場しました。 Pg_upgradeは構造のみをダンプし、それらを新しいクラスターに復元します。ただし、データファイルをディスク上にあるままコピーします。これは、データファイルを論理形式にダンプしてから再挿入するよりもはるかに高速です。これは、数分または数時間の範囲のダウンタイムを意味するため、小規模なデータベースには十分です。これは、多くのシナリオで許容できる時間です。このプロセスをさらに高速化するハードリンク(Windowsではジャンクションポイント)を作成するだけのリンクモードもあります。しかし、私の個人的な観点からは、本番マスターサーバーでこのようなセットアップを実行するのは危険すぎます。その理由を簡単に説明します。問題が発生した場合、リンクモードを使用してアップグレードされた新しいサーバーを起動すると、突然本番データベースがなくなり、フェイルオーバーする必要があります。さらに悪いことに、バックアップから復元する必要があります。つまり、アップグレードに失敗しただけでなく、追加のダウンタイムが発生しただけです。次回は承認を得て頑張ってください。

    現在、アップグレードに長いダウンタイムを費やす余裕がない多くの人々は、SlonyやLondisteなどのトリガーベースのレプリケーションソリューションを使用してアップグレードを行っています。元のサーバーの実行中にデータを複製し、最小限のダウンタイムで切り替えることができるため、これは優れたソリューションです。ただし、実際にはいくつかの問題があります。そのうちの1つは、トリガーベースのソリューションは、特に2、3年に1回だけ実行し、アップグレードのみを実行する場合は、セットアップが面倒なことが多いことです。また、テーブルを見逃したり、テーブルを間違った順序で追加したりして、完全なコピーを取得できないことも簡単です。 これを実際に目撃しました。アップグレードを行う人々は、トリガーベースのレプリケーションを毎日使用していました。 。もう1つの問題は、トリガーベースのソリューションがソースデータベースにかなりの負荷をかけ、レプリケーションがアクティブ化されるとデータベースサーバーが過負荷になるためにアップグレードが不可能になる場合があることです。最後になりましたが、多くの場合、トリガーベースのレプリケーションが実際にデータを新しいサーバーに移動するのに非常に長い時間がかかる場合があります。 私がアップグレードプロジェクトに関与した最後の機会に、トリガーベースのソリューションはデータベースをコピーして変更に追いつくのに約1か月かかりました。はい、1か月です。

    PostgreSQL 9.4には、新しくより優れたオンラインアップグレード問題ソリューションを設計するための新たなスタートを提供する論理デコード機能が搭載されています。 AXLEプロジェクトの一環として、論理デコードと上記の手法を組み合わせたツールを作成しました。このソリューションは、以前のアプローチの問題のほとんどを解決します。 Uni-Directional Replication PostgreSQL拡張機能(略してUDR)は、先行書き込みログ(WAL)の論理デコードを使用して論理レプリケーションを実行します。このおかげで、マスターサーバーへの影響は物理ストリーミングレプリケーションとほぼ同等であるため、実行中のシステムで進行中のアップグレードによって発生する追加の負荷は最小限に抑えられます。また、物理バックアップと論理バックアップの両方を使用して、新しいノードを初期化するためのツールも提供します。既存のフィジカルスタンバイをUDRスタンバイに変えることもできます。また、論理レプリケーションシステムであるため、クロスバージョンレプリケーションをサポートするように設計することができます。

    つまり、UDRをpg_upgradeと組み合わせて使用​​することで、最小限のダウンタイム、短い絶対時間、実行中のシステムへの影響を最小限に抑えて、主要なPostgreSQLバージョンのオンラインアップグレードを実行できるようになりました。

    これが実際にどのように見えるかの例:

    • 既存のインスタンスのpg_basebackupを実行します。
    • 元のインスタンスとbasebackupによって作成されたインスタンスの間にUDRレプリケーションを設定します。
    • 新しいインスタンスをPg_upgradeします。
    • UDRにその間に発生した変更を再生させます。
    • トラフィックを新しいインスタンスに切り替えます。

    より詳細な手順のハウツーについては、PostgreSQLwikiのUDRオンラインアップグレードガイドを参照してください。 UDRソースは、PostgreSQL gitサーバーの2ndquadrant_bdrリポジトリ(bdr-plugin / nextブランチ)で利用できます。

    最後に、UDRはオンラインアップグレードツールであるだけでなく、レプリケーションソリューションでもあるため、物理的なストリーミングレプリケーションの代わりに、通常のレプリケーションのニーズに使用できます。さらに、一時テーブルを作成する機能、複数のOLTPデータベースから1つのビッグデータウェアハウスデータベースに複製する機能、データベースの一部だけを複製する機能など、いくつかの利点があります。

    この取り組みにより、PostgreSQL9.4以降から新しいメジャーバージョンにアップグレードする際にダウンタイムの考慮事項が問題にならなくなることを願っています。

    これらの結果につながる研究は、助成金契約番号318633に基づいて、欧州連合の第7フレームワークプログラム(FP7 / 2007-2013)から資金提供を受けています。


    1. オプティマイザーがバッファープールの知識を使用しない理由

    2. 葯から1つのストアドプロシージャを呼び出して、返されるrefcursorを変更する方法は?

    3. 参加によるPostgresqlアップデート

    4. MariaDBでサフィックスを使用して日番号を返す方法