15 Oracle Globally Distributed Databaseによるデータ主権の実現

クラウド・コンピューティングの普及に伴い、特にデータとそのプライバシの保護に関する業界標準に関する関心が高まっています。今日、ほとんどの組織は、データがどこに保存され、誰がデータにアクセスできるかを把握することを必要としています。これにより、データ・レジデンシの管理が重大な関心事項になり、データを特定の地理的な場所に格納することが要求されるようになりました。

オンプレミスであれクラウドであれ、市民のデータをより厳格に保護および管理するために、すでに120か国以上がデータ保護に関するなんらかの国際プライバシ法に関与しています。

データ主権の概要

データ主権とは、一般的に、データが作成された地域に固有の規制によってデータが管理されることを指します。これらのタイプの規制では、データの保存場所、データへのアクセス方法、データの処理方法およびデータのライフサイクルが指定されることがあります。

国境やパブリック・クラウド・リージョンをまたぐデータの急増に伴い、100か国以上でデータの保存場所と転送方法に関する規制が可決されました。特に、個人を特定できる情報(PII)は、それが収集される国の法律およびガバナンス構造の対象となることが増えています。多くの場合、他の国へのデータ転送は、その国が同様のレベルのデータ保護を提供しているかどうか、およびその国が科学捜査で協力するかどうかに基づいて制限または許可されます。

データ主権の要件は地域の規制に基づくため、アプリケーション・アーキテクチャは様々なものになる可能性のあるます。そのいくつかは次のとおりです。

  • データを特定の地理的な場所で物理的に保存する必要があります。たとえば、特定の国または複数の国で構成される地域の境界内です。データが遠隔地に保存されていないかぎり、データにリモートでアクセスして処理することは問題ありません。技術的な観点からは、これは、永続データを物理的に格納するデータベース、オブジェクト・ストア、メッセージング・ストアなどのデータ・ストアが特定の地理的な場所にある必要があることを意味します。ただし、データを処理するためのビジネス・ロジックを持つアプリケーション・ランタイムは、地理的な場所の外に配置できます。このようなアプリケーション・パーツの例には、アプリケーション・サーバー、モバイル・アプリケーション、APIゲートウェイ、ワークフローなどがあります。

  • データを特定の地理的な場所で物理的に保存および処理する必要があります。この場合、データの保存と処理は、定義された地理的な場所内で行う必要があります。

Oracle Globally Distributed Databaseでデータ主権を実装するメリット

Oracle Globally Distributed Databaseはデータ主権の要件を満たし、低レイテンシと高可用性を必要とするアプリケーションをサポートします。

  • シャーディングにより、データの様々な部分を様々な国や地域に配置できるため、データを特定の管轄区域に配置する必要がある規制要件を満たします。

  • また、特定のデータを利用者の近くに保存することもサポートしています。Oracle Globally Distributed Databaseは、優れたランタイム・パフォーマンス、柔軟なスケーリング、ライフサイクル管理により、シャード・データベースのライフサイクル全体(デプロイ、スキーマ作成、データ依存ルーティング)を自動化します。

  • リレーショナル・スキーマ、SQL、およびその他のプログラム・インタフェース、複雑なデータ型のサポート、オンライン・スキーマの変更、マルチコア・スケーラビリティ、高度なセキュリティ、圧縮、高可用性、ACIDプロパティ、読取り一貫性、JSONを使用した開発者の俊敏性などを含むエンタープライズRDBMSの利点も提供します。

Oracle Globally Distributed Databaseによるデータ主権の実装

Oracle Globally Distributed Databaseは、様々なコンピュータ、オンプレミスまたはクラウドの多数のデータベース(シャード)にデータ・セットのセグメントを分散します。これらのシャードは、世界中の複数のリージョンにデプロイできます。これにより、Oracle Globally Distributed Databaseは、データ・レジデンシを考慮してグローバルに分散したデータベースを作成できます。

特定のデータベース内のすべてのシャードは、単一の論理データベースとしてアプリケーションに提供されます。アプリケーションは、実行する問合せに基づいて適切なシャードにシームレスに接続されます。たとえば、米国にデプロイされたアプリケーション・インスタンスがヨーロッパに存在するデータを必要とする場合は、特別な処理の必要なくアプリケーション・リクエストがEUデータ・センターにシームレスにルーティングされます。

図15-1 Oracle Globally Distributed Databaseのアーキテクチャ



また、Real Application Security (RAS)、仮想プライベート・データベース(VPD)、Oracle Database VaultなどのOracle Databaseのセキュリティ機能を使用して、リージョン内でもデータ・アクセスをさらに制限できます。たとえば、すべてのEU諸国ではなく、一部の国からのデータのみがEUリージョンの管理者に表示されるようにさらに制限できます。データ主権リージョン内では、Oracle Data Guardを使用して複数のデータ・センターにデータをレプリケートできます。

Oracle Globally Distributed Databaseの管理インタフェースにより、グローバル・メタデータを制御し、物理データベース(レプリカ)、それに含まれるデータ、レプリケーション・トポロジなどを表示できます。Oracle Globally Distributed Databaseは、ノードが追加または削除されたときにデータの再分散を処理します。

様々なリージョンからデータを実際にコピーすることなく、世界中のレポートにアクセスできます。シャーディングでは、どのリージョンからもデータをコピーせずにマルチシャード・レポートを実行できます。Oracle Globally Distributed Databaseは、データが存在するノードに問合せをプッシュします。

Oracle Globally Distributed Databaseは、次の側面に焦点を当てた包括的なデータ主権ソリューションを提供します。

  • データ・レジデンシ: データを複数のシャードに分散でき、地理的に異なる場所にデプロイできます。

  • データ処理: アプリケーション・リクエストは、アプリケーションの実行場所に関係なく、正しいシャードに自動的にルーティングされます。

  • データ・アクセス: Oracle Databaseの仮想プライベート・データベース機能を使用して、リージョン内のデータ・アクセスをさらに制限できます。

  • 派生データ: データをOracle Databaseに格納し、Oracle Databaseの機能を使用して派生データの増加を抑制します。

  • データ・レプリケーション: Oracle Globally Distributed DatabaseをOracle Data Guardとともに使用して、同じデータ主権リージョン内でデータをレプリケートできます。

データ主権のユースケース

架空の大手金融機関であるShard Bankは、複数の国でユーザーにクレジット・サービスを提供しようとしています。クレジット・サービスが提供される各国には独自のデータ・プライバシ規制があり、個人を特定できる情報(PII)データを当該国に保存する必要があります。

データへのアクセスを制限する必要があり、ある国のデータ管理者は他の国のデータを表示できません。このユースケースのソリューションは、様々な国でシャードが構成されたユーザー定義のシャーディングと、データ・アクセス制御のためのReal Application Security (RAS)または仮想プライベート・データベース(VPD)です。

データ主権ソリューションの概要

このデータ主権ソリューションは、国内のデータ記憶域を提供し、すべてのデータのグローバル・ビューもサポートしています。

次の例は、複数のリージョンにまたがるOCIデータ・センターとオンプレミス間のハイブリッドOracle Globally Distributed Databaseユーザー定義デプロイを示しています。この構成では、すべてのデータをローカルに保存および処理できます。各データベース(各主権リージョン内)はシャードになり、シャードは単一のシャード・データベースに属します。Oracle Globally Distributed Databaseでは、1つのシャード(1か国)のデータを問い合せることができます。Oracle Globally Distributed Databaseでは、(すべての国からデータを問合せできる)マルチシャード問合せがサポートされています。

図15-2 シャード・データベース



グローバル・シャード・データベースは、存在する必要がある国を示すキーでシャードされます。国内のアプリケーションは通常どおりローカル・データベースに接続し、すべてのデータはローカルに保存および処理されます。

マルチシャード問合せは、シャード・コーディネータに転送されます。コーディネータは問合せをリライトし、必要なデータがある各シャード(国)に送信します。コーディネータは、すべての国からの結果を処理して集計し、結果を返します。

Oracle Globally Distributed Databaseでは、次の機能でこのユースケースが可能になります。

  • 国内の問合せのシャードへの直接ルーティング。
  • ユーザー定義のシャーディング方法により、国の範囲またはリストを使用して、シャード間でデータをパーティション化できます。
  • Oracle Active Data Guardを使用してレプリケーションを自動構成し、レプリカを国内に制限します。
  • 既存のデータベースをシャード・データベースに変換および追加するためのデータ・フェデレーション・サポート(Oracle Database 21c以降)。詳細は、フェデレーテッド・シャード・データベースへの既存の非シャード・データベースの結合を参照してください。
  • シャーディング・キーの自動導出(Oracle Database 21c以降)。

この方法のメリットは次のとおりです。

  • 各シャードは、国内のクラウドまたはオンプレミスに配置できます。
  • シャードは様々なクラウド・プロバイダを使用でき(マルチクラウド戦略)、シャードのレプリカを異なるクラウドまたはオンプレミスに配置できます。
  • オンライン再シャーディングにより、クラウド間、またはクラウドとオンプレミスとの間でデータを移動できます。
  • データ主権の厳格な施行により、不注意によるリージョンをまたいだデータ漏えいを防止します。
  • データの重複を低減した単一のマルチモデル・ビッグ・データ・ストア。
  • 1つのリージョン/LOB内の計画/計画外停止時間が他のリージョン/LOBに影響しないため、より優れた障害分離が実現します。
  • ビジー状態のパーティションとシャードを必要に応じて分割できます。
  • 完全なACIDプロパティのサポートは、トランザクション・アプリケーションにとって重要です。

データ主権のデプロイ・トポロジ

このユースケースの例では、フランクフルト(リージョン1 FRA)、アムステルダム(リージョン2 AMS)、およびロンドン(リージョン3 LON)の3つのリージョンにまたがるOracle Cloud Infrastructureにシャード・データベースを作成します。

各リージョンは、シャード・ディレクタ(仮想マシン・グローバル・サービス・マネージャ(GSM))と1つのシャード(それぞれシステム・データベース・シャード1、2および3)をホストし、リージョン1 (FRA)はシャード・カタログ(システム・データベースGSMカタログ・データベース)をホストします。

図15-3 データ主権のデプロイ・トポロジ



データ主権ユース・ケースの構成

次のトピックのステップを実行して、Oracle Globally Distributed Databaseデータ主権ユース・ケースを構成します。

3つのOCIリージョンすべてにおけるVCNネットワークの構成

Oracle Cloud Infrastructure (OCI)では、仮想クラウド・ネットワークは、インスタンスが実行される従来のネットワークの仮想バージョンです。各リージョン(FRA、AMSおよびLON)に仮想クラウド・ネットワーク(VCN)をデプロイして構成します。

各リージョンで、パブリックとプライベートの2つのサブネットを持つVCNを作成します。
  1. プライベート・サブネットの新しいルート表を作成し、プライベート・サブネットに関連付けます。デフォルトのルート表はパブリック・サブネットにのみ使用し、プライベート・サブネットには専用のプライベート・ルート表を設定することが適切です。
  2. インターネット・ゲートウェイを作成し、デフォルトのルート表に関連付けます。
  3. ネットワーク・アドレス変換(NAT)ゲートウェイであるサービス・ゲートウェイを作成し、プライベート・サブネットのルート表に関連付けます。
FRAの例:
  • VCN名/CIDER: シャーディングVCN FRA 10.0.0.0/16
  • パブリック・サブネット名/CIDER: public_fra 10.0.5.0/24
  • プライベート・サブネット名/CIDER: private_fra 10.0.6.0/24

ノート:

シャーディング・デプロイメントで使用されるすべてのリージョンでステップを繰り返します。サブネットCIDERは各リージョンで異なる必要があり、VCN/サブネット名にリージョン接頭辞を指定する必要があります。
3つのリージョン間のリモートVCNピアリングの構成

リモートVCNピアリングは、異なるリージョンにある2つのVCNを接続することで、トラフィックをインターネット経由でルーティングすることなく、プライベートIPアドレスを使用してVCNのリソースが通信できるようにするプロセスです。

トポロジ内の他の2つのリージョンに接続するために、各リージョンに2つのリモート・ピアリング接続(RPC)を構成します。
  1. RPCを構成するステップについては、RPCを使用したリモートVCNピアリングに関する項を参照してください。
  2. パブリック・サブネット/VCNのルーティング・ルールを構成します。
  3. プライベート・サブネット/VCNのルーティング・ルールを構成します。
  4. セキュリティ・ルールを構成します。
たとえば、リージョン1 (FRA)では次のようになります。

リージョン間のネーミング解決のためのプライベートDNSの構成

各リージョンのドメインごとにパブリック・サブネットとプライベート・サブネットのプライベート・ビューを作成し、1つのゾーン内に合計6つのプライベート・ゾーンを作成します。その後、すべてのエントリが各プライベート・ゾーン構成に追加されます。

  1. プライベートDNSゾーンを作成および管理するには、プライベートDNSに関する項を参照してください。
  2. 次のタスクに進む前に、すべての名前が正しく解決されていることを確認します。

ノート:

これらの手順は、名前を正しく解決できるように、すべてのVCN/VMの各リージョンで実行する必要があります。
各リージョンへのグローバル・サービス・マネージャのインストール

Oracle Global Data Servicesグローバル・サービス・マネージャ(GSM)は、Oracle Globally Distributed Databaseによって、アプリケーションからシャード・データベース内の正しいシャードに問合せをルーティングするために使用されます。

ソフトウェアをダウンロードし、次のタスクを実行します。
  • グローバル・サービス・マネージャ(Oracle Database 19c)ソフトウェアを要塞VMにダウンロードします。
  • 最新バージョンのOPatchを適用します。
  • 新しくインストールされたグローバル・サービス・マネージャ(Oracle Database 19c)に、利用可能な最新のOracle Databaseバンドル・パッチを適用します。
各リージョンにGSMをインストールするには:
  1. iSCSIを使用して200 GBのブロック・ストレージを作成します。GSM用OCIコンピュートでiSCSIを構成します。ブロック・ストレージを/u01にマウントします。
    ブロック・ストレージのマウント・プロセスについては、一貫性のあるデバイス・パスを使用したボリュームへの接続に関する項を参照してください。
  2. rootユーザーとして、必要なすべてのパッケージをインストールします。
    # yum install -y oracle-database-preinstall-19c
  3. rootユーザーとして、/u01oracle:oinstallによって所有されていることを確認します。
    # chown oracle:oinstall /u01
  4. GSMソフトウェアを指定されたシャード・ディレクタVMにダウンロードし、サイレント・モードでインストールします。
  5. gsm home/etc/oratabに追加します。
    gsm:/u01/app/oracle/product/19.0.0.0/dbhome_1:N
  6. 最新のOPatchバージョンを適用します。
  7. Oracle Database 19cに利用可能な最新のバンドル・パッチ・バージョンを適用します。
  8. ファイアウォールでGSMポートを開きます。
    $ systemctl start firewalld.service
    $ systemctl enable firewalld.service
    $ firewall-cmd --permanent --zone=public --add-port=1522/tcp # firewall-cmd --reload
    $ firewall-cmd --permanent --zone=public --list-ports
    1522/tcp 22/tcp 
    
  9. アプリケーションがGSMに接続できるように、GSM VMに割り当てられたセキュリティ・リストで必要なポートが開いていることを確認します。
シャード・カタログおよびシャード・データベースのTNSエントリの収集

シャード・カタログおよびシャード・データベースの構成用にGSMサーバーを準備するには、TNSエントリのコレクションが必要です。シャード・カタログは、シャード・カタログ・オブジェクトを格納するPDBにのみアクセスする必要があります。ただし、シャード・データベースには、アプリケーション・スキーマを格納する各共有CDBおよびPDBのエントリを準備します。

  1. シャード・カタログ・データベースおよびすべてのシャード(シャード・カタログとシャード)にアクセスするためのtnsnamesエントリを準備します。
  2. これらのエントリをGSM VMの$ORACLE_HOME/network/admin/tnsnames.oraに追加します。

    ノート:

    接続文字列のホスト名にはFQDNを使用します。
    db_unique_name =
      (DESCRIPTION =
        (ADDRESS = (PROTOCOL = TCP)(HOST = host_name_fqdn)(PORT = 1521))
        (CONNECT_DATA =
          (SERVER = DEDICATED)
          (SERVICE_NAME = cdb_service_name)
        )
      )
    
    pdb_name =
      (DESCRIPTION =
        (ADDRESS = (PROTOCOL = TCP)(HOST = host_name_fqdn)(PORT = 1521))
        (CONNECT_DATA =
          (SERVER = DEDICATED)
          (SERVICE_NAME = pdb_service_name)
        )
      )
    
シャード・カタログの構成

シャード・カタログは、Oracle Globally Distributed Databaseのメタデータを管理します。シャード・カタログ・データベースとなるリージョン1 (FRA)でデータベースを構成します。

  1. すべてのDBCSインスタンスに接続し、sqlnet.oraファイルに構成されているsqlnet暗号化アルゴリズムを更新し、クライアントおよびサーバーでサポートされるアルゴリズムとしてRC4_256暗号化方法を追加します。

    ノート:

    AES暗号化はGSM: Enh 29496977 - GDS ONLY USES RC4_256 TYPE ENCRYPTIONではデフォルトではサポートされていないため、AES暗号化を有効にするためにパッチが必要です。AES暗号化を有効にするには、Oracle Database 19cでパッチを適用します。ただし、このパッチはOracle Database 21cでは必要ありません。

    ノート:

    RC4_256アルゴリズムは、Oracle Database 19cでのみ必要です。
  2. Oracle Globally Distributed Databaseの要件を使用して、シャード・カタログ・データベースを構成します。
    SQL> alter system set open_links=16 scope=spfile;
    SQL> alter system set open_links_per_instance=16 scope=spfile;
    SQL> shu immediate
    SQL> startup
    
  3. シャード・カタログ・データベースでユーザーを構成します。
    SQL> alter user gsmcatuser account unlock.
    SQL> alter user gsmcatuser identified by password;
    # Switch to PDB dedicated for catalog database
    SQL> alter session set container=catalog_db_pdb;
    SQL> create user mysdbadmin identified by password;
    SQL> grant connect, create session, gsmadmin_role to mysdbadmin; 
    SQL> grant inherit privileges on user SYS to GSMADMIN_INTERNAL;
    
シャード・データベースの構成

各リージョンに、シャード・データベース構成でシャードになるデータベースを構成します。

  1. すべてのDBCSインスタンスに接続し、sqlnet.oraファイルに構成されているsqlnet暗号化アルゴリズムを更新し、クライアントおよびサーバーでサポートされるアルゴリズムとしてRC4_256暗号化方法を追加します。

    ノート:

    AES暗号化はGSM: Enh 29496977 - GDS ONLY USES RC4_256 TYPE ENCRYPTIONではデフォルトではサポートされていないため、AES暗号化を有効にするためにパッチが必要です。AES暗号化を有効にするには、Oracle Database 19cでパッチを適用します。ただし、このパッチはOracle Database 21cでは必要ありません。

    ノート:

    RC4_256アルゴリズムは、Oracle Database 19cでのみ必要です。
  2. 次のコマンドを実行します。
    SQL> alter database flashback on;
    SQL> alter system set dg_broker_start=true;
    SQL> alter user GSMROOTUSER account unlock;
    SQL> alter user GSMUSER account unlock;
    SQL> alter user GSMADMIN_INTERNAL account unlock;
    SQL> alter user GSMROOTUSER identified by password;
    SQL> alter user GSMUSER identified by password;
    SQL> alter user GSMADMIN_INTERNAL identified by password;
    SQL> grant sysdg to gsmuser;
    SQL> grant SYSBACKUP to gsmuser;
    SQL> grant sysdg to GSMROOTUSER;
    SQL> grant SYSBACKUP to GSMROOTUSER;
    SQL> alter system set global_names=false;
    SQL> shu immediate
    SQL> startup
    # Switch to PDB used as shared database
    SQL> alter session set container= pdb_name;
    SQL> grant read,write on directory DATA_PUMP_DIR to GSMADMIN_INTERNAL;
    SQL> grant sysdg to gsmuser;
    SQL> grant SYSBACKUP to gsmuser;
    
Oracle Globally Distributed Databaseの作成

グローバル・サービス・マネージャ・リスナーを構成し、シャード・カタログ・データベースを作成して、すべてのシャードを構成に追加します。デプロイメント・ステップでは、すべてのシャードを単一のグローバル・データベースとして構成します。

  1. シャード・カタログを構成します。

    ノート:

    デフォルトでは、システム管理のシャーディングが構成されています。他のシャーディング方法が必要な場合は、シャード・カタログの作成時に指定します。
    GDSCTL> create shardcatalog -database catalog_pdb_tns_entry -sharding user -user
          mysdbadmin/password -region region1
  2. GSMリスナーを追加して起動します。GDSCTLからリスナーを実行します。
    GDSCTL> add gsm -gsm sharddirector1 -listener 1522 -pwd password -catalog pdb_tns_entry
          -region region1
  3. 次のテンプレートを使用して、構成にシャードを追加します。シャード・データベースごとに繰り返します。

    FRAでシャードを追加します。

    GDSCTL> add invitednode shard_hostname
    GDSCTL> add cdb -connect cdb_conn_tns_entry -pwd gsmrootuser_pwd
    GDSCTL> add shardspace -shardspace primary_shardspace_fra
    GDSCTL> add shard -cdb cdb_conn_string -connect pdb_conn_string
     -shardspace primary_shardspace_fra -pwd gsmuser_pwd -deploy_as PRIMARY

    AMSでシャードを追加します。

    GDSCTL> add invitednode shard_hostname
    GDSCTL> add cdb -connect cdb_conn_tns_entry -pwd gsmrootuser_pwd
    GDSCTL> add shardspace -shardspace primary_shardspace_ams
    GDSCTL> add shard -cdb cdb_conn_string -connect pdb_conn_string
     -shardspace primary_shardspace_ams -pwd gsmuser_pwd -deploy_as PRIMARY

    LONでシャードを追加します。

    GDSCTL> add invitednode shard_hostname
    GDSCTL> add cdb -connect cdb_conn_tns_entry -pwd gsmrootuser_pwd
    GDSCTL> add shardspace -shardspace primary_shardspace_lon
    GDSCTL> add shard -cdb cdb_conn_string -connect pdb_conn_string
     -shardspace primary_shardspace_lon -pwd gsmuser_pwd -deploy_as PRIMARY
  4. シャード・データベース構成をデプロイします。
    GDSCTL DEPLOYコマンドを実行して、次の出力を取得します。
    GDSCTL> deploy
    deploy: examining configuration...
    deploy: requesting Data Guard configuration on shards via GSM
    deploy: shards configured successfully
    The operation completed successfully
    
  5. アプリケーションからの着信接続リクエストを処理するために、シャードでグローバル・データベース・サービスを作成します。グローバル・サービスは、従来のデータベース・サービスの拡張です。グローバル・サービスでは、従来のサービスのすべてのプロパティがサポートされます。シャード・データベースの場合、グローバル・サービスに追加のプロパティが設定されます。「グローバル・データベース・サービスの作成と開始」を参照してください。
    たとえば、データベース・ロール、レプリケーション・ラグの許容範囲、クライアントとシャードの間のリージョン・アフィニティなどです。読取り/書込みトランザクション・ワークロードの場合は、シャード・データベースのプライマリ・シャードのデータにアクセスするために、単一のグローバル・サービスを作成します。Active Data Guardを使用した高可用性シャードの場合は、個別の読取り専用グローバル・サービスを作成します。
    GDSCTL> add service -service oltp_rw_srvc -role primary
「シャード・データベースへの移行」で説明されている方法を使用して、データをシャードにロードします
セッション・ベースのアプリケーション・コンテキスト・ポリシーの実装

単一シャード問合せとマルチシャード問合せの両方に対して、Oracle Database仮想プライベート・データベース(VPD)機能と組み合せて、シャード・データベースに行レベルのデータ・アクセス制御を追加します。Oracle Global Data Servicesグローバル・サービス・マネージャ(GSM)は、Oracle Globally Distributed Databaseで、アプリケーションからシャード・データベース内の正しいシャードに問合せをルーティングするために使用されます。

  1. シャード・カタログにユーザー・アカウントとサンプル表を作成します。
    connect / as sysdba
    alter session enable shard ddl;
    create user bt identified by bt;
    grant dba, all privileges to bt;
    
    --CREATE USER sysadmin_vpd IDENTIFIED BY password CONTAINER = CURRENT;
    CREATE USER sysadmin_vpd IDENTIFIED BY password ; --CONTAINER = CURRENT;
    
    GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER, ALTER SESSION TO sysadmin_vpd;
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_vpd;
    GRANT EXECUTE ON DBMS_RLS TO sysadmin_vpd;
    
    CREATE USER CT identified by ct;
    CREATE USER DT identified by dt;
    GRANT CREATE SESSION TO CT, DT;
    
    GRANT EXECUTE ON sys.exec_shard_plsql to bt, ct, dt, sysadmin_vpd;
    
    connect bt/bt
    create tablespace set ts1 in shardspace shd1;
    CREATE SHARDED TABLE customers (custid number, name varchar2(20), constraint pk1 primary key(custid)) PARTITION BY CONSISTENT HASH(custid) PARTITIONS AUTO TABLESPACE SET ts1;
    -- user-defined:
    -- CREATE SHARDED TABLE customers (custid number primary key, name varchar2(20)) PARTITION BY RANGE (custid) (PARTITION p1 values less than (100) TABLESPACE  ts1, PARTITION p2 values less than(200) TABLESPACE  ts2, PARTITION p3 values less than(300) TABLESPACE  ts11, PARTITION p4 values less than(400) TABLESPACE  ts12);
    
    insert into customers(custid, name) values(1,'CT');
    insert into customers(custid, name) values(2,'DT');
    insert into customers(custid, name) values(4,'ET');
    insert into customers(custid, name) values(5,'FT');
    commit;
    
    GRANT READ ON customers TO sysadmin_vpd;
    
    create sharded table orders(oid number not null, custid number not null, constraint ordfk foreign key(custid) references customers(custid)) partition by reference(ordfk);
    -- user-defined:
    -- CREATE SHARDED TABLE orders(oid number not null, custid number not null, constraint orders_fk1 foreign key(custid) references customers(custid)) partition by reference(orders_fk1);
    
    insert into orders values(9876, 1);
    insert into orders values(8888, 2);
    insert into orders values(7777, 2);
    insert into orders values(7771, 4);
    insert into orders values(7772, 4);
    insert into orders values(7773, 5);
    commit;
    
    GRANT READ ON orders TO CT, DT;
    
  2. データベース・セッション・ベースのアプリケーション・コンテキストを作成します。
    CONNECT sysadmin_vpd/password
    CREATE OR REPLACE CONTEXT orders_ctx USING orders_ctx_pkg;
  3. アプリケーション・コンテキストを設定するPL/SQLパッケージを作成します。
    CONNECT sysadmin_vpd/password
    CREATE OR REPLACE PACKAGE orders_ctx_pkg IS 
    --  PROCEDURE set_custnum SHARD_ENABLE;
      PROCEDURE set_custnum;
     END;
    /
    CREATE OR REPLACE PACKAGE BODY orders_ctx_pkg IS
      --PROCEDURE set_custnum SHARD_ENABLE
      PROCEDURE set_custnum
      AS
        custnum NUMBER;
        cnt number;
        cname varchar2(256);
      BEGIN
        -- workaround for bug 33131789: run a CSQ before SET_CONTEXT
        SELECT count(*) INTO cnt FROM BT.CUSTOMERS;
        SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') INTO cname FROM dual;
        SELECT custid INTO custnum FROM BT.CUSTOMERS WHERE name = cname;
        DBMS_SESSION.SET_CONTEXT('orders_ctx', 'cust_no', custnum);
      EXCEPTION
       WHEN NO_DATA_FOUND THEN NULL;
      END set_custnum;
    END;
    /
    
  4. アプリケーション・コンテキストのPL/SQLパッケージを実行するログオン・トリガーを作成します。
    /* create trigger fails to propagate from catalog.
        CREATE TRIGGER set_custno_ctx_...
        DDL Error: ORA-06550: line 1, column 7:
        PLS-00352: Unable to access another database \'GDS$CATALOG.SYSLOCLINK\'
        ORA-06512: at "GSMADMIN_INTERNAL.EXECUTECOMMAND", line 166
        ORA-06550: line 1, column 7:
        PLS-00201: identifier \'SYS@GDS$CATALOG.SYSLOCLINK\' must be declared
        ORA-06550: line 1, column 7:
        PL/SQL: Statement ignored
        ORA-06512: at "SYS.DBMS_GSM_FIXED", line 3764
        ORA-06512: at "SYS.DBMS_GSM_FIXED", line 3866
        ORA-06512: at "GSMADMIN_INTERNAL.EXECUTECOMMAND", line 118
        ORA-06512: at "GSMADMIN_INTERNAL.EXECUTEDDL", line
      So we create it on shards as well manually. => Use alter session enable  shard operations before creating the trigger.
    */
    /* execute sys.exec_shard_plsql('CREATE OR REPLACE TRIGGER set_custno_ctx_trig AFTER LOGON ON DATABASE  BEGIN  sysadmin_vpd.orders_ctx_pkg.set_custnum; END;');
    ORA-03753: The procedure cannot be propagated.
    */
    -- run on catalog and all shards
    CONNECT sysadmin_vpd/password
    CREATE OR REPLACE TRIGGER set_custno_ctx_trig AFTER LOGON ON DATABASE  BEGIN  sysadmin_vpd.orders_ctx_pkg.set_custnum; END;
    /
    
  5. ログオン・トリガーをテストします。
    connect dt/dt
    SELECT SYS_CONTEXT('orders_ctx', 'cust_no') custnum FROM DUAL;
    connect ct/ct
    SELECT SYS_CONTEXT('orders_ctx', 'cust_no') custnum FROM DUAL;
    /* Example output:
    SQL> SELECT SYS_CONTEXT('orders_ctx', 'cust_no') custnum FROM DUAL;
    CUSTNUM
    --------------------------------------------------------------------------------
    2
    */
    
  6. シャード・カタログおよびシャードで、ユーザー・アクセスをオーダーのみに制限するPL/SQLポリシー関数を作成します。
    /* IF you see following error while propagation of DDL to shards, create the function on catalog and each shards manually.
        PLS-00352: Unable to access another database \'GDS$CATALOG.SYSLOCLINK\'
    */
    connect sysadmin_vpd/password
    CREATE OR REPLACE FUNCTION get_user_orders(
      schema_p   IN VARCHAR2,
      table_p    IN VARCHAR2)
     RETURN VARCHAR2
     AS
      orders_pred VARCHAR2 (400);
      cnum NUMBER;
     BEGIN
      SELECT NVL(SYS_CONTEXT('orders_ctx', 'cust_no'), 0) INTO cnum FROM dual;
      --orders_pred := 'custid = '||cnum;
      orders_pred := 'custid = SYS_CONTEXT(''orders_ctx'', ''cust_no'')'; 
     RETURN orders_pred;
    END;
    /
    
  7. 新しいセキュリティ・ポリシーを作成します。
    execute sys.exec_shard_plsql(' SYS.DBMS_RLS.ADD_POLICY (object_schema => ''BT'',   object_name => ''orders'', policy_name => ''orders_policy'',  function_schema => ''sysadmin_vpd'', policy_function  => ''get_user_orders'', statement_types  => ''select'',  policy_type => DBMS_RLS.CONTEXT_SENSITIVE,  namespace => ''orders_ctx'',  attribute => ''cust_no'')');
    
    -- exec sys.exec_shard_plsql('sys.DBMS_RLS.DROP_POLICY(''BT'', ''orders'', ''orders_policy'')');
    -- exec sys.exec_shard_plsql('sys.DBMS_RLS.REFRESH_POLICY(''BT'', ''orders'', ''orders_policy'')');
    
  8. 新しいポリシーをテストします。
    connect ct/ct
    select * from bt.orders;
    connect dt/dt
    select * from bt.orders;
    /*
    connect dt/dt
    SQL> select * from bt.orders;
           OID     CUSTID
    ---------- ----------
          8888        2
          7777        2
          
    connect ct/ct
    SQL> select * from bt.orders;
           OID     CUSTID
    ---------- ----------
          9876        1
    */