Snowflakeのレプリケーション(複製)に関するメモ (Architect)

# これは何？

Snowflakeのレプリケーションに関してまとめてみたメモ。
レプリケーション(replication)は日本語マニュアルでは「複製」と表現される。
あとはプレビュー中の機能が多い印象。

## 公式情報

- [レプリケーション(複製)](https://docs.snowflake.com/ja/user-guide/account-replication-intro)
    - レプリカを作成する機能
        - 元データ(ソース)を「プライマリオブジェクト」という
        - 元データ(ソース)を持つアカウントを指して「ソースアカウント」という
        - レプリケーション先を「セカンダリオブジェクト」という
        - レプリケーション先のアカウントを指して「ターゲットアカウント」という
    - AWS、GCP、Azureのリージョン全般でサポートされる
    - グループ
        - 複製グループ
            - 1つ以上のターゲットアカウントにユニットとして複製される、ソースアカウント内のオブジェクトの定義済みコレクション
            - 複製されたオブジェクトへの「読み取り専用」アクセスを提供する
                - つまり、セカンダリオブジェクトに対して[書き込み(更新)できない](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-read-only-secondary-objects)
        - フェールオーバーグループ
            - フェールオーバーも可能な複製グループ
            - セカンダリフェールオーバーグループが、プライマリフェールオーバーグループに昇格すると、「読み取り/書き込み」アクセスが利用可能になる
    - グループを使わない複製/フェールオーバーもある
        - `ALTER DATABASE`で[設定できる](https://docs.snowflake.com/ja/sql-reference/sql/alter-database#database-replication-and-failover-syntax)
            - `ALTER DATABASE <name> ENABLE REPLICATION TO ACCOUNTS <account_identifier>`
            - `ALTER DATABASE <name> ENABLE FAILOVER TO ACCOUNTS <account_identifier>`
        - グループを使った複製に移行したい場合は、先に無効にする必要がある
            - [こちら](https://docs.snowflake.com/ja/user-guide/account-replication-config#transitioning-from-database-replication-to-group-based-replication)参照
            - [SYSTEM$DISABLE_DATABASE_REPLICATION](https://docs.snowflake.com/ja/sql-reference/functions/system_disable_database_replication)
    - エディション差分
        - 複製自体は全エディションで使用できる
        - 一部機能はBusiness Critical以上で利用できる
            - アカウントオブジェクト（データベースおよび共有以外）複製
            - フェールオーバーグループ
            - [Tri-Secret Secure](https://docs.snowflake.com/ja/user-guide/account-replication-intro#label-database-replication-encryption)で保護されたデータ
- [複製できるオブジェクト](https://docs.snowflake.com/ja/user-guide/account-replication-intro#replicated-objects)
    - データベース
        - ただし以下はNG
            - 仮テーブル(テンポラリーテーブル/Temporary table)
            - 外部テーブル
            - イベントテーブル
    - シェア(共有)
        - プロバイダーとして自分で作成したシェアオブジェクトが対象
        - 一方で共有されたものは複製できない
    - (Business Critical以上) [ユーザー](https://docs.snowflake.com/ja/user-guide/account-replication-intro#user-replication)
    - (Business Critical以上) [ロール](https://docs.snowflake.com/ja/user-guide/account-replication-intro#role-replication)
    - (Business Critical以上) [ロールと権限の付与](https://docs.snowflake.com/ja/user-guide/account-replication-intro#replication-of-roles-and-grants)
    - (Business Critical以上) [ウェアハウス](https://docs.snowflake.com/ja/user-guide/account-replication-intro#warehouse-replication)
    - (Business Critical以上) [リソースモニター](https://docs.snowflake.com/ja/user-guide/account-replication-intro#resource-monitor-replication)
    - (Business Critical以上) [パラメーター（アカウントレベル）](https://docs.snowflake.com/ja/user-guide/account-replication-intro#parameter-replication)
    - (Business Critical以上) [ネットワークポリシー](https://docs.snowflake.com/ja/user-guide/account-replication-intro#network-policy-replication)
    - (Business Critical以上) [統合(インテグレーション/integration)](https://docs.snowflake.com/ja/user-guide/account-replication-intro#integration-replication)
        - ただし以下はプレビュー中
            - ストレージ統合
            - 外部アクセス統合
- [複製スケジュール](https://docs.snowflake.com/ja/user-guide/account-replication-intro#replication-schedule)
    - スケジュールによる自動更新が推奨されている
        - `REPLICATION_SCHEDULE`パラメーターで設定する
            - [こちら](https://docs.snowflake.com/ja/sql-reference/sql/create-replication-group)参照
    - 一度に1回の更新のみが実行される
    - 次回の更新がスケジュールされているときに更新がまだ実行中の場合、現在実行中の更新が完了後に次回の更新が遅れて開始される
    - 更新の実行中は、セカンダリフェールオーバーグループをプライマリグループに昇格できない
    - ターゲットアカウントでスケジュールされた複製を一時停止してから昇格する
    - スケジュールされた複製を一時停止しても、現在進行中の更新操作は停止されない
        - 複製処理が完了後、以降のスケジュールが停止される
- [下位エディションのアカウントへの複製](https://docs.snowflake.com/ja/user-guide/account-replication-intro#replication-schedule)
    - デフォルトではエラーになりうる
        - デフォルトではBusiness Critical（またはそれ以上）のアカウントから、機密データを下位エディションのアカウントに誤って複製することを防ぐ動きになる点に注意する
        - その手のデータ(HIPAA HITRUST規制、PHI データ)が含まれているときに複製しようとするとエラーになる
    - エラー回避
        - `CREATE <オブジェクト>` か `ALTER <オブジェクト>` のSQLの実行時に`IGNORE EDITION CHECK句`を含めることで、エラーの回避は可能(デフォルトの動作を上書きする)
- [複製に関する考慮事項](https://docs.snowflake.com/ja/user-guide/account-replication-considerations) (いっぱいある...)
    - オブジェクトは、1つのフェールオーバーグループにのみ存在できる
    - 複製先が異なる場合は、1つのオブジェクトは複数の複製グループに所属できる
    - オブジェクトは、フェールオーバーグループと複製グループの両方に含めることはできない
    - セカンダリ（レプリカ）オブジェクトを、プライマリ複製グループまたはフェールオーバーグループに追加することはできない
    - [複製の権限](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-privileges)
        - デフォルトではACCOUNTADMINで各種処理を実行できる
        - カスタムロールで実行したい場合は以下の権限を考慮
            - 複製グループの`OWNERSHIP`
            - フェールオーバーグループの`OWNERSHIP`
            - `CREATE REPLICATION GROUP` (複製グループを作成する権限)
            - `CREATE FAILOVER GROUP` (フェールオーバーグループを作成する権限)
            - `FAILOVER` (セカンダリフェールオーバーグループを昇格する権限)
            - `REPLICATE` (セカンダリグループを更新する権限)
            - `MODIFY` (オブジェクトの設定やプロパティを変更する機能)
            - `MONITOR` (オブジェクト内の詳細を表示する権限)
    - [複製グループ間での複製と参照](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-references-across-replication-groups)
        - [ダングリングリファレンス/dangling references](https://docs.snowflake.com/ja/user-guide/database-replication-considerations#dangling-references)に注意する
            - 要は[オブジェクト間の依存関係](https://docs.snowflake.com/ja/user-guide/object-dependencies)に関するの話
                - BY_NAME (CTASを実行するとき、AS以降に指定するテーブル名とか)
                - BY_ID (ストレージ統合、外部ステージとか)
                - BY_NAME_AND_ID (マテリアライズドビューとか)
            - 依存関係を持っているオブジェクトが複製時に存在しなかった等の理由でエラーになる可能性がある
            - [OBJECT_DEPENDENCIES](https://docs.snowflake.com/ja/sql-reference/account-usage/object_dependencies)
                - オブジェクトの依存関係を確認する際に参照
            - [ストリームの考慮点](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#streams)
                - こんなエラーが出る
                    - `Primary database: the source object ''<object_name>'' for this stream ''<stream_name>'' is not included in the replication group.
Stream replication does not support replication across databases in different replication groups.`
                - 回避策
                    - プライマリデータベースに、ストリームとそのベースオブジェクトの両方を含めておく
                    - ストリームを含むデータベースと、ストリームが参照するベースオブジェクトを含むデータベースが、同じ複製グループかフェールオーバーグループに含まれていること
            - [ネットワークポリシーの考慮点](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#network-policies)
                - こんなエラーが出る
                    - `Dangling references in the snapshot. Correct the errors before refreshing again.`
                    - ネットワークポリシーの参照と割り当ての複製では、参照されるオブジェクトと、ネットワークポリシーが割り当てられているオブジェクトも複製される
                    - サポートするオブジェクト型を適切に複製しないと、Snowflakeはターゲットアカウントでリフレッシュ操作に失敗する
                - 回避策
                    - [ネットワークポリシーがネットワークルールを使用する場合](https://docs.snowflake.com/ja/user-guide/network-policies#adding-network-rules-to-a-network-policy)は、ネットワークルールが作成されたスキーマを含むデータベースを含めること([こちら](https://docs.snowflake.com/ja/user-guide/network-rules#replication-of-network-rules)参照）
                    - [ネットワークポリシーがアカウントに関連付けられている場合](https://docs.snowflake.com/ja/user-guide/network-policies#activating-a-network-policy-for-your-account)は、 OBJECT_TYPES リストに NETWORK POLICIES と ACCOUNT PARAMETERS を含めること
                    - [ネットワークポリシーがユーザーに関連付けられている場合](https://docs.snowflake.com/ja/user-guide/network-policies#activating-a-network-policy-for-your-account)は、 OBJECT_TYPES リストに NETWORK POLICIES と USERS を含めること
                - 複製する時の具体例
                    - [こちら](https://docs.snowflake.com/ja/user-guide/account-replication-security-integrations#replicating-network-policy-references-and-assignments)参照
            - [シークレットの考慮点](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-secrets)
                - 以下を単一の複製グループまたはフェイルオーバーグループで指定する
                    - シークレットを含むデータベース
                    - シークレットを参照するUDFsやプロシージャを含むデータベース
                    - シークレットを参照する統合を
            - [複製およびTime Travel](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-objects-in-target-accounts)
                - セカンダリデータベース用に新たにTime Travel(タイムトラベル)、Fail-safe(フェールセーフ)が作成される
                - プライマリデータベースとは独立している
            - [複製と外部テーブル](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-external-tables)
                - 複製しようとするとエラーが発生する
                    - `003906 (55000): SQL execution error:
Primary database contains an external table '<database_name>'. Replication of a database with external table is not supported`
                - 回避策
                    - 複製されていない別のデータベースに外部テーブルを移動する
                    - プライマリデータベースのクローンを作成し、クローンから外部テーブルを削除してから、クローンデータベースを複製する
                    - ターゲットアカウントでセカンダリデータベースを昇格した後、データベースに外部テーブルを再作成する
                - プライマリに外部テーブルが存在する状態でセカンダリに降格(セカンダリ側の操作でセカンダリがプライマリに昇格)した場合、エラーが発生する
                    - `003958 (55000): SQL execution error:
Secondary database contains an external table '<table_name>'. Replication of a database with external table is not supported.`
                - 回避策
                    - セカンダリになるデータベース内に外部テーブルが含まれないようにしておく
            - [複製とストリーム](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-streams)
                - 以下のストリームはサポートされない
                    - 外部テーブル
                    - 共有から作成したデータベースのテーブル/ビュー
                    - 異なる複製グループ/フェールオーバーグループに、ストリームとソースオブジェクトが存在する(分離されている)場合
                        - ストリームとそのストリームが参照するオブジェクトは同じグループに入れておく必要があるということ
                    - [データ重複の回避](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#avoiding-data-duplication)
                        - ここに書いてある事例は見ておくとよさそう
                    - [ストリーム複製およびTime Travel](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#stream-replication-and-time-travel)
                        - ここに書いてある事例(図)は見ておくとよさそう
            - [複製とタスク](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-tasks)
                - タスクが複製されるかどうか
                    - [こちら](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-scenarios)参照
                    - 基本的には「タスク作成後、再開も実行もされていないもの」は複製されない
                - すべてのセカンダリタスクは[中断される](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#resumed-or-suspended-state-of-replicated-tasks)
                - フェールオーバー後(セカンダリ昇格後)、[順次タスクがスケジュールされる](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#task-runs-after-a-failover)
    - [複製経由以外の方法](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-objects-in-target-accounts)でターゲットアカウントにオブジェクトを作成した場合
        - ターゲットアカウントがソースアカウントからリフレッシュされると、グローバル識別子を持たないターゲットアカウント内にある OBJECT_TYPES リストのすべてのアカウントオブジェクト型が削除される
- [複数のアカウント間にわたるデータベースとアカウントオブジェクトの複製](https://docs.snowflake.com/ja/user-guide/account-replication-config)
    - アカウントとデータベースオブジェクトの複製を有効にし、オブジェクトを更新する手順が書いてある
        - [こちら](https://docs.snowflake.com/ja/user-guide/account-replication-config#workflow)参照
        - ソースアカウントでフェールオーバーグループを作成
        - ターゲットアカウントでフェールオーバーグループをレプリカとして作成
        - その後、初回複製はスケジュールが設定されていれば自動で実施される
    - [アカウントオブジェクトとデータベースの複製](https://docs.snowflake.com/ja/user-guide/account-replication-config#replicating-account-objects-and-databases)
        - ORGADMIN権限で以下の実行が必要
            - `SELECT SYSTEM$GLOBAL_ACCOUNT_SET_PARAMETER('<organization_name>.<account_name>', 'ENABLE_ACCOUNT_DATABASE_REPLICATION', 'true');`
    - [ターゲットアカウントのスクリプトによって作成されたオブジェクトにグローバル IDs を適用する](https://docs.snowflake.com/ja/user-guide/account-replication-config#apply-global-ids-to-objects-created-by-scripts-in-target-accounts)
        - 複製経由「以外」の方法でターゲットアカウントにアカウントオブジェクトを作成すると、リフレッシュ時に削除される
        - これを回避する時の方法が書かれてある
            - 初期複製の前に、ターゲットアカウントにのみ存在するユーザーまたはロールを手動でソースアカウントに再作成する
            - SYSTEM$LINK_ACCOUNT_OBJECTS_BY_NAME関数を使用して、両方のアカウントで同じ名前を持つオブジェクトをターゲットアカウントでリンクする
            - ユーザーおよびロールの初期複製を行う
- [API 統合のリモートサービスの更新](https://docs.snowflake.com/ja/user-guide/account-replication-config#updating-the-remote-service-for-api-integrations)
    - Snowflakeアカウント毎に統合のID/アクセス管理（IAM）エンティティが必要になる
    - ソースアカウントで設定した時と同じ要領でターゲットアカウント用の設定が必要
    - 各クラウドベンダー毎の設定方法に従って対応する
- [複数のアカウントにわたるセキュリティ統合の複製](https://docs.snowflake.com/ja/user-guide/account-replication-security-integrations)
    - 各種事例が載っているのでそれを参照する
        - [SAML2 セキュリティ統合の複製](https://docs.snowflake.com/ja/user-guide/account-replication-security-integrations)
        - [SCIM セキュリティ統合の複製](https://docs.snowflake.com/ja/user-guide/account-replication-security-integrations#replicating-scim-security-integrations)
        - [OAuth セキュリティ統合の複製](https://docs.snowflake.com/ja/user-guide/account-replication-security-integrations#replicating-oauth-security-integrations)
- [ステージ、パイプ、ロード履歴の複製](https://docs.snowflake.com/ja/user-guide/account-replication-stages-pipes-load-history)
    - こちらは全般的にプレビュー機能とのこと
- [複製コストについて](https://docs.snowflake.com/ja/user-guide/account-replication-cost)
    - ターゲットアカウントで費用が発生する
    - データ転送
        - リージョン間でデータを転送するのでそのコストがかかる
        - [こちら](https://docs.snowflake.com/ja/user-guide/cost-understanding-data-transfer)参照
    - コンピューティングリソース
        - データをコピーする際にSnowflakeが提供するコンピュートリソースを使用するのでそのコストがかかる
        - [こちら](https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf)参照
            - Table 5: Serverless Feature Credit Table
    - ストレージコスト
        - セカンダリデータベースのデータの標準ストレージコスト
        - [クローンテーブルをセカンダリデータベースに複製](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-cloning)すると、物理データも複製されるため、アカウントのデータストレージの使用量が増加する
    - 実際にかかったコスト
        - [DATABASE_REPLICATION_USAGE_HISTORY](https://docs.snowflake.com/ja/sql-reference/functions/database_replication_usage_history)を確認する
    - 複製に失敗した時
        - 失敗までに消費したリソースのコストはもちろんかかる
        - 最初の複製またはリフレッシュ操作が失敗する前にコピーされたデータは、その後のリフレッシュ操作（14日以内に実行された場合）で再利用できる
- [アカウントオブジェクトのフェールオーバー](https://docs.snowflake.com/ja/user-guide/account-replication-failover-failback)
    - セカンダリフェールオーバーグループをプライマリフェールオーバーグループに昇格
        - `ALTER FAILOVER GROUP...PRIMARY`を実行
    - ターゲットアカウントでスケジュールされた複製を再開
        - `ALTER FAILOVER GROUP...RESUME`を実行
- [ALTER FAILOVER GROUP](https://docs.snowflake.com/ja/sql-reference/sql/alter-failover-group#label-alter-failover-group)について
    - フェールオーバーグループのプロパティ変更のために使用する
        - ソースアカウントから実行する場合
            - セカンダリフェールオーバーグループの自動更新の複製スケジュールを設定または更新する
            - 複製とフェールオーバーが有効になっているターゲットアカウントを追加または削除する
            - 共有またはデータベースを別のフェールオーバーグループに移動する
            - 他、名前変更など
        - ターゲットアカウントから実行する場合
            - セカンダリフェールオーバーグループをプライマリに昇格する
                - オブジェクトのフェールオーバーグループをフェールオーバーする
            - ソースアカウントからターゲットアカウントのオブジェクトを手動更新する
            - スケジュールされた複製を停止/再開する
    - 必要な権限
        - REFRESH
            - フェールオーバーグループの`OWNERSHIP`か`REPLICATE`
        - PRIMARY
            - フェールオーバーグループの`OWNERSHIP`か`FAILOVER`
        - データベースをフェールオーバーグループに追加する
            - データベースの`MONITOR`
        - フェールオーバーグループに共有を追加する
            - 共有の`OWNERSHIP`

## ざっくりポイント

- セカンダリデータベースは、プライマリとは異なるクラウドベンダーおよびリージョンに配置することができる
- セカンダリは読み取り専用
    - 昇格してプライマリになると書き込みができる
- レプリケーション時のデータ転送とコンピュートリソースのコストがかかるのはターゲットアカウント(セカンダリ)側
- 外部テーブルに注意
- スケジュールによる自動更新が基本
- 下位エディションへの複製に注意

## 所感

ん〜なんか難しい。
あんま使わないからイメージも湧きづらい...かといって試すのも結構重いか。

プレビュー機能も多いから、実践的に使われているものなのかどうかよくわからん。
リージョンまたぎやクラウドベンダーまたぎのシェアのためには必須の機能なので、どちらかというとその目的のために使われているのかな(というか使わざるを得ない)