Oracle Cloudを活用した自動テストデータリフレッシュについて

alt

こんにちは。 エンジニアリング統括部 第1開発部 システムアーキテクチャBITAグループの石井です。

私の所属するグループでは、社内基幹システムにおける新規要件のシステム要件検討/提案や、システム信頼性向上のための施策立案/実行、 また内製開発エンジニアのための開発環境改善などを主な業務としています。

2020年12月にTECH Streetにて、『基幹システム刷新における品質担保のためのデータベースを用いた自動テストの構築とデータリフレッシュについて』という話をさせて頂いたのですが、かなり駆け足での発表となってしまいましたので、今回はその後半でお話したOarcle Cloudのソリューションを利用した自動テストデータリフレッシュに関する内容についてより詳しく解説させて頂きます。

Eventへのリンク

【イベントレポート】内製開発エンジニア勉強会 ~社内システムを内製化して学び・悩み・悟ったアレコレ~ - TECH Street (テックストリート)

▼ 概要

まずは、今回の施策とそれを行うに至った背景を説明します。

弊社の基幹システムのひとつに Advanced Recruitment Consulting Support system (以下ARCSと表記します) というものがあり、このシステムが利用しているデータベース(以下DBと表記します)は大小複数のシステムによって同時にアクセス/更新が行われているという現状があります。

ARCSで自動テストを実施するにあたり当初DBアクセス部分をモック化することを検討しましたが、それではARCSシステム改修外で発生したテーブルのカラム変更や、ストアドプロシージャの仕様変更などのDB定義変更が発生した際のシステム改修による影響から発生する障害検知を事前に行うことができず、自動テストの結果が全量正常完了となった場合でも、リリース後の障害をゼロにできないという問題から、自動テストのDBアクセスについてはモック化を行わずに常に最新のDB定義をもってテストを実施する事としました。

alt
データベースを使用した自動テスト実装
しかし、実際にデータベースを用いて自動テストを行うように実装したところ、データリフレッシュの問題が発生しました。 特定の試験などでは、複数の前提条件を満たすために複合的に連続して複数の自動テスト実施する必要があり、DB更新時のトランザクションを全てロールバックするような手段を使用することができず、結果的には全量のテスト実行を行った後に自動テスト用DBのデータが様々な状態に更新され、この状態で再度自動テストを実行するとテストの再現性が失われる(つまりテストが毎回違った結果となってしまう)という状態に陥ってしまいました。

この問題を解決させるため、開発チームでは全量の自動テスト実施する際にインスタントな自動テスト用DBを作成し、テストが完了したら破棄するといった仕組みを検討した結果、Oracle Cloud の機能活用によってそれを実現しました。

採用したソリューションは主に以下の2つです。 (※何故同じ課題について2つの方式をそれぞれ構築したのかについては後日、TECH Streetのレポートにて)

  1. Oracle Exadata Cloud@Customer (以下ExaCCと表記します)のSnap Clone
  2. Oracle Cloud Service(以下OracleCSと表記します)の以下の機能
    • Container Database Clone (以下CDBと表記します)
    • Pluggable Database Clone (以下PDBと表記します)

これらがどういう仕組みで実現されているのかをこれから解説します。

▼ データリフレッシュの前提条件

データリフレッシュソリューションを説明する前に、今回の自動テストDB運用に対する要件/課題を整理します。 今回の仕組みを構築するにあたり、最低限必要となる要件については検討/整理した結果、以下の通りとなりました。

1.バックアップの取得/復元またはマスタデータへの影響を与えない運用法があること

自動テストを実施するためのデータについてはテストコードと対になっており、基本的にテストコードが実装されるタイミングでテストデータ作成を行い、テストに必要となる可変条件はテストヘルパーによってテストコードからDBへテスト実行時に投入されますが、マスタデータや一部の前提条件となる非トランザクションデータについては事前に自動テスト用マスタデータとして自動テスト用のDBに投入済みとなります。

テスト実行の際は、このマスタデータが含まれるDBに対して影響を与えない形でテスト実行する方法を検討する必要があります。

2.有限のデータ容量を効率よく利用すること

自動テストによってデータ投入や削除を行うため、DBの容量については注意する必要があります。 また、テストマスタとしてベースとなるステージングDBは最初からそれなりの容量があり、考えなしにコピーを量産するとすぐにストレージの容量が不足します。 この施策によって作られる環境は本番受入用のマスターブランチに対する変更に対して実施するほかに、複数の並行して進捗するプロジェクトでそれぞれの単体テストを実施する際にもそれぞれ発行される事を想定しているため、1環境あたりのDB容量の使用量が多いと調達環境のストレージを枯渇させる恐れがあり、データを効率的に利用する方法を考える必要があります。

3.テスト開始時または終了時に自動的なデータリフレッシュを行えること

自動テストは開発プロジェクトで実施する場合はプロジェクト全体でのビルド時チェックの他に、開発者が実施する手動実行でも使用できる必要があり、受入テストや再帰テスト(リグレッションテスト)では自動化されたCI環境の上で実行される必要があります。 そのため、ソリューションの完成時にはCLIによる自動化ができる方式であることが前提となります。

▼ 解決方法1:Oracle Exadata Cloud@Customer を利用したデータリフレッシュソリューション

ソリューション説明

ひとつ目の解決方法として検討したのは、ExaCCのSnap Cloneです。 これはOracle12cから利用できる機能で、複製元DB(マスタDB)に対してスナップショットDBというものを作成し、DBに対する変更差分についてはスナップDBを、変更のない部分についてはテストマスターを参照することで、変更差分のみを持った使い捨てDBを作成できるというものです。

丁度弊社では、数年前からパフォーマンステストや本番DB準拠のテスト実行のため(※)にExaCCを導入しており、その環境を使用出来る目途が立ったため、Snap Cloneによる問題解決にチャレンジしました。
(※ ARCSの本番DBはExadataを使用しておりフルフラッシュストレージであるため通常テスト/開発用に用意されている通常のOracleでは検証が困難なパターンが存在するため) alt

  • メリット
    • データ全量をコピーするわけではないため、高速にスナップショットDBを構築することができる
    • データ容量が差分のみ保持されるため、少ないストレージで複数のスナップDBを保持することができる
  • デメリット
    • データアクセスする際にマスタDBとスナップDB両方を合わせた仮想DBとしてアクセスするためにパフォーマンスは低下する
      ※ 約10,000ケースのテストを実行するのに4時間かかる場合、スナップDBを使用した速度低下はプラス30~45分程だった
    • マスタDBはスナップDBが1つでも存在する場合ReadOnlyとなり、すべてのスナップDBを破棄しないと再構築/更新ができない
ソリューション構成

ソリューション設計を基に、運用フローを検討します。 基本的には前提条件を満たしつつ、手動実行/自動実行 そして 改修プロジェクトが請負開発での発注となった場合を考慮して、開発前提条件(契約前提条件)を維持できるようにする必要があることに注意します。 alt

No 概要 タイミング 詳細
既存DBからエクスポート 初回のみ 既存のAUTOTEST_DB(ARCS/BAKS)からDB定義、およびデータをエクスポートする
CDB作成 初回のみ ARCS/BAKS用のCDBを作成する。原則1つのみ(全PJT共通)
PDBへインポート 初回のみ エクスポートしたDB定義、データをCDB作成時に自動生成されるPDBへインポートする
テストマスタ作成 プロジェクト開始 プロジェクト開始時に要望を受けてプロジェクト専用のテストマスタを作成する。
SnapCloneDB作成 プロジェクト開始/プロジェクト要望に応じて テストマスタよりプロジェクト開発、または自動テストで利用するSnapCloneDBを作成する。
修正パッチ適用 SnapCloneDB作成後 以下のパッチを適用する。
 ・DBの不整合状態を修復する(preferenceやIndex、MaterialsView等)
 ・他プロジェクト開発に発生したDDL/DMLを適用する(時系列に沿って適用)
適用完了後、DB接続情報をプロジェクトへ払い出す。
- DDL/DML適用 プロジェクト開発中 開発に伴うDDL/DMLは随時払い出したSnapCloneDBに対して実行する。
(誤ったDDLを適用し、修正不可の場合等は改めてSnapCloneDB払出を依頼する)
- DDL/DML格納 納品まで 開発に伴うDDL/DMLの最終適用版を保管する。
(最終試験ではプロジェクト開始時点のマスタDBに対してプロジェクト成果物を適用し自動テスト結果を得るため)
- SnapCloneDB削除 プロジェクト要望に応じて 要望があった場合、SnapCloneDBを削除する。
再作成する際は⑤、⑥を実行する。
- テストマスタ削除 プロジェクト終了時 プロジェクト終了時にテストマスタを削除する。(リソース開放のため)

SnapCloneで全量テストを実行した後SnapCloneを含んだDBインスタンスの容量を確認したところ、数重MBしか変更していなかったため、DBストレージを節約したい場合に非常に有効だと思います。

しかし、実際にテストマスタよりSnapConeを作成する際に私たちがやってみた方法では一部の内容がClone結果に引き継がれませんでした。何らかの方法できちんとCloneする方法はありそうでしたが、自動テストに必要な部分だけ修正すれば問題がないため、修正バッチを作成しCIの自動化プロセスの中でバッチ実行するように構成しています。

具体的にはOracle databaseの以下のような項目です。

  • システム定義プリファレンス
  • インデックス
  • マテリアライズビュー

また実際の運用ではプロジェクトごとにスタート時の状態断面が異なるため、バックアップやレストアといった点についても併せて検討しています。

参考文献

▼ 解決方法2:Oracle Cloud Service を利用したデータリフレッシュソリューション

ソリューション説明

ふたつ目の解決方法として検討したのは、OracleCSのCDB Clone/PDB Cloneです。

OracleのCloud Serviceでは仮想マシンインスタンス1つに対して1つのCDBが割り当てられ、その中にPDBという形で複数のデータベースを持つことができます。これらCDB/PDBはOracleCSの機能で高速にCloneを行うことができ、PDBは作成/コピー/削除が用意に可能であるため、インスタントのテストDBとして活用できないか注目しました。 また、ExaCCで注意を払っていたデータ容量についても、クラウドサービスを利用する形になったため、必要なストレージはある程度の利用量を払うことで容量を気にする必要がなく使用できるようになったため複雑な仕様を作る必要がなくなりました。 alt

出典:アシスト 徹底解説!Oracle Database 12cのすべて Vol.1

Oracle Multitenantの特徴を簡単に説明すると以下の通りとなります。

  • CDBにある、複数のPDBは1つのインスタンスで動いている
  • PDBの実体はデータファイルだが、CDBにプラグインすることで、PDB単位で独立したデータベース同等のふるまいをする
  • PDBは独立しているDBとみなされるため、同じCDBにプラグインされていてもスキーマ名は競合しない
  • PDB群はインスタンスのリソースを共同利用する

Oracle Cloud Service の導入については、たまたま我々がこのソリューション検討をしているタイミングと時を同じくして弊社の開発環境DBをオンプレからクラウドに移設するという施策が行われ、急遽使えるようになりました。 現在はこちら側の方法で開発環境でCIが構築されています。

そして、これらの特徴を踏まえて実際にどのようにデータリフレッシュを行うのかというと、以下の様にCI環境(今回はAzure DevOps)のビルドパイプラインを活用して、CI環境上から直接SSHでコマンドを順次実行し、必要な操作を自動テスト実行時に同時に行われるように構成します。Azure DevOpsが高機能であることと、OarcleCSが基本的な操作をCLIで行えることによって、別途バッチ処理など作成する必要もなくこのような環境を構築することができます。 alt

  • メリット
    • OracleCSの機能を使うことにより指定したCDB/PDBのCloneを高速に行うことができる
    • OracleCS上で行える操作については基本的にCLIが提供されており、SSHでコマンド実行することで外部からの操作が可能
    • CPU/メモリ/ストレージなどのハードウェアリソースについて通常開発で使用する分にはほぼ上限を気にする必要がない
  • デメリット
    • ソリューションの一部が外部のSaaS/PaaSに構築されるためセキュアに利用することも含め、自動化構成は工夫が必要
    • (当然だが) CPU/メモリ/ストレージはハイスペックかつ長時間に大量に使用するとどんどんお金がかかる
ソリューション構成

机上ではこちらのソリューションをつかって前提条件となる要件を満たすことが出来たため、実際に運用フローを検討していきます。

解決方法1と同じように前提条件を満たしつつ、手動実行/自動実行 そして 改修プロジェクトが請負開発での発注となった場合を考慮して、開発前提条件(契約前提条件)を維持できるようにする様に構成を行いました。 alt

No 概要 タイミング 概要
プロジェクト用PDB作成 プロジェクト開始時
PJT用のDBをAutoteTestDBからPJT用のDBシステムへクローン
クローンしたDBを開発DBとしてプロジェクトチームへ払い出す
バックアップ用CDB/PDB作成 プロジェクト開始時 受入用のDBシステムにAutoteTestDBからDBをクローン
受入用DBシステムはコスト削減のため、利用時のみ稼働
バックアップ取得 プロジェクト開始時 払出時点のDBのバックアップを取得する
このバックアップはPDB破損またはプロジェクト完了時の受入テストで使用する
バックアップからレストア プロジェクト終了時 受入用のDBシステムにて、バックアップからDBを復元
DDL/DML適用
最終受入テスト
プロジェクト終了時 復元したDBに対し、必要DDL/DMLを適用し、自動テスト実行

OracleCSのPDB/CDB Cloneを利用する場合には以下の制約に注意する必要があります。

  • ひとつのインスタンスにはひとつのCDBしか作成することはできない
  • バックアップはCDB単位でしか行うことができない
  • インスタンス=CDBとなるため、CDBに対して大量のPDBを接続するとCPUやメモリは全てのPDBで共有され、低スペックだとパフォーマンス問題が発生する
  • CDBのストレージサイズは拡張可能だが、逆に不要になった場合は減らすことができない(※CDBのサイズを減らしたい場合は再度小さいサイズでCDBを作り直しPDBを引っ越す必要がある)
  • PDBクローンを行う際、クローン元のPDBはReadOnlyにしなくてはならない(Oracle12cの制約で後のバージョンではホットクローンが可能になっている様子)
コスト削減プラン

プロジェクトにて開発中または、スケジューリングによって全量の自動テストを行うため、この環境を利用しますが前述の通りクラウドサービスは使えば使うほど、電源が入っていればその時間分コストが発生します。

そのため、構築後にコストカットの検討を行う必要がありました。
最後にOracleCSのCDB/PDBを自動テストに利用する場合のコスト感についてお話します。
※ 弊社環境の特徴として自動テスト用の開発用DBのデータ容量が大きめである部分ことに注意してください。

基本的な方針としては以下の通りとなります。

  1. 利用していない時間帯/曜日についてはデータベースを停止する
  2. 高負荷で使用する時間帯と低負荷で使用する時間帯でCPUの性能を調整する
  3. インスタントな環境(バックアップやレストア環境)は普段は停止しておく

そのうえで我々が上記構成に対して設定したコストカットプランが以下の様になります。 作成直後とコストカットプランに変更後の差分を記載しましたので見比べてみて下さい。
(インスタンスの性能変更や、起動/停止などもAzure DevOpsのパイプラインを使用してスケジュール実行しています) alt

参考文献

▼ まとめ

一般的に自動テストを実施する際にはデータベースはモック化するなどするのが一般的で、実際のデータベースを使用する事はバッドパターンとして有名です。

しかし、運用が長期化した業務システムなど一筋縄ではいかない前提条件でシステムのモダナイゼーションを行う機会もあるかと思います。そういった環境ではベストプラクティスに拘ることなく、手持ちの環境や使えるソリューションを駆使して解決方法をよく考えてみれば、その状況に即した解決策を見出すことができるはずです。

今回のパターンでは実際にやりきることができ、業務システムを柔軟に仕様変更を行っていく過程において品質担保上非常に堅牢なシステムを構築することができました。このノウハウが皆さんのチャレンジの助けになれば幸いです。

alt

石井 孝典 Kousuke Ishii

エンジニアリング統括部 第1開発部 システムアーキテクチャBITAグループ リードエンジニア

2017年中途入社。 新卒で独立系SIerに入社。宇宙開発/自動車R&D/製薬・製造/金融/物流など業種を問わず様々なシステム開発プロジェクトに従事。 プログラマからSE/プロジェクトマネージャーを経て、事業目線で業務システムの未来像を描き推進できる環境を求めてインテリジェンス(現パーソルキャリア)に入社。 基幹業務システムの刷新にシステムアーキテクトとして参画。現在は同システムの改善や、周辺システム連携のアーキテクチャ構築を担当。

※2021年1月現在の情報です。