(57)【特許請求の範囲】
【請求項１】
ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置であって、
前記データベースにおけるコミットされて保存された複数の保存データ要素と、当該複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部と、
前記複数の未保存データ要素に対して、前記クエリを実行する第１のクエリ実行部と、
前記第１のクエリ実行部により前記クエリが実行された後に、前記複数の保存データ要素に対して、前記クエリを実行する第２のクエリ実行部と、
前記第２のクエリ実行部により前記クエリが実行された後に、前記第２のクエリ実行部による前記クエリの実行中に保存された少なくとも１つの保存データ要素に対して、前記クエリを実行する第３のクエリ実行部と
を含み、
前記第１のクエリ実行部は、前記複数の未保存データ要素のうちの前記クエリにより抽出された特定の未保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の未保存データ要素による更新に関するトランザクションの状態に基づいて判定し、
前記第２のクエリ実行部は、前記複数の保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、装置。
【請求項２】
前記第１のクエリ実行部は、
前記トランザクションが前記クエリを実行している場合は、前記特定の未保存データ要素を前記クエリの結果に含め、
前記トランザクションが前記クエリを実行しておらず、当該トランザクションの状態がコミット済みである場合は、前記特定の未保存データ要素で、前記複数の保存データ要素のうちの当該特定の未保存データ要素による更新の対象である保存データ要素を置き換える、請求項１の装置。
【請求項３】
前記第２のクエリ実行部は、
前記特定の保存データ要素の更新のための未保存データ要素が記憶されていない場合、前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態がアボートである場合、及び、前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態が実行中であり、前記トランザクションが前記クエリを実行していない場合は、当該特定の保存データ要素を前記クエリの結果に含め、
前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態がコミット済みである場合は、当該特定の未保存データ要素で当該特定の保存データ要素を置き換える、請求項１の装置。
【請求項４】
前記第３のクエリ実行部は、前記少なくとも１つの保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、請求項１の装置。
【請求項５】
前記第３のクエリ実行部は、
前記特定の保存データ要素の更新のための未保存データ要素が記憶されていない場合、前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態がアボートである場合、及び、前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態が実行中である場合は、当該特定の保存データ要素を前記クエリの結果に含め、
前記特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、前記トランザクションの状態がコミット済みである場合は、当該特定の未保存データ要素で当該特定の保存データ要素を置き換えた後、前記第３のクエリ実行部の処理を再実行する、請求項４の装置。
【請求項６】
前記記憶部は、前記複数の未保存データ要素の各未保存データ要素に関連付けて、当該各未保存データ要素による更新を実行したトランザクションを識別するトランザクションＩＤを記憶する、請求項１乃至請求項５の何れかの装置。
【請求項７】
前記記憶部は、前記複数の保存データ要素の各保存データ要素、前記各未保存データ要素、及び前記トランザクションＩＤを１つのエントリとして記憶する、請求項６の装置。
【請求項８】
前記記憶部は、前記トランザクションの状態を示すトランザクション状態情報を前記トランザクションＩＤに関連付けて記憶する、請求項７の装置。
【請求項９】
前記第１のクエリ実行部、前記第２のクエリ実行部、及び前記第３のクエリ実行部は、それぞれ、前記クエリにより抽出されたデータ要素を含む前記エントリ中の前記トランザクションＩＤにより前記トランザクション状態情報を参照しながら処理を実行する、請求項８の装置。
【請求項１０】
前記第２のクエリ実行部は、前記クエリにより抽出された保存データ要素に前記エントリ中で付随する未保存データ要素がコミット済みのトランザクションにより更新されていた場合は、当該未保存データ要素で当該保存データ要素を置き換えて、当該エントリに関連するキーを保存し、
前記第３のクエリ実行部は、前記キーを用いて前記クエリを実行する、請求項９の装置。
【請求項１１】
ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置であって、
前記データベースにおけるコミットされて保存された複数の保存データ要素と、当該複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素と、当該複数の保存データ要素の当該複数の未保存データ要素による更新に関する複数のトランザクションを識別する複数の識別情報とを対応付けて記憶する記憶部と、
前記複数の未保存データ要素に対して、前記クエリを実行し、当該複数の未保存データ要素のうちの前記クエリにより抽出された特定の未保存データ要素を、前記複数の識別情報のうちの当該特定の未保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、前記クエリの結果に含める第１のクエリ実行部と、
前記第１のクエリ実行部により前記クエリが実行された後に、前記複数の保存データ要素に対して、前記クエリを実行し、当該複数の保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を、前記複数の識別情報のうちの当該特定の保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、前記クエリの結果に含める第２のクエリ実行部と、
前記第２のクエリ実行部により前記クエリが実行された後に、前記第２のクエリ実行部による前記クエリの実行中に保存された少なくとも１つの保存データ要素に対して、前記クエリを実行し、当該少なくとも１つの保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を、前記複数の識別情報のうちの当該特定の保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、前記クエリの結果に含める第３のクエリ実行部と
を含む、装置。
【請求項１２】
ＮｏＳＱＬ型のデータベースに対するクエリを処理する方法であって、
前記データベースにおけるコミットされて保存された複数の保存データ要素と、当該複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部を含み、
前記複数の未保存データ要素に対して、前記クエリを実行する第１のステップと、
前記第１のステップで前記クエリが実行された後に、前記複数の保存データ要素に対して、前記クエリを実行する第２のステップと、
前記第２のステップで前記クエリが実行された後に、前記第２のステップでの前記クエリの実行中に保存された少なくとも１つの保存データ要素に対して、前記クエリを実行する第３のステップと
を含み、
前記第１のステップでは、前記複数の未保存データ要素のうちの前記クエリにより抽出された特定の未保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の未保存データ要素による更新に関するトランザクションの状態に基づいて判定し、
前記第２のステップでは、前記複数の保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、方法。
【請求項１３】
ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置として、コンピュータを機能させるプログラムであって、
前記コンピュータを、
前記データベースにおけるコミットされて保存された複数の保存データ要素と、当該複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部と、
前記複数の未保存データ要素に対して、前記クエリを実行する第１のクエリ実行部と、
前記第１のクエリ実行部により前記クエリが実行された後に、前記複数の保存データ要素に対して、前記クエリを実行する第２のクエリ実行部と、
前記第２のクエリ実行部により前記クエリが実行された後に、前記第２のクエリ実行部による前記クエリの実行中に保存された少なくとも１つの保存データ要素に対して、前記クエリを実行する第３のクエリ実行部と
して機能させ、
前記第１のクエリ実行部は、前記複数の未保存データ要素のうちの前記クエリにより抽出された特定の未保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の未保存データ要素による更新に関するトランザクションの状態に基づいて判定し、
前記第２のクエリ実行部は、前記複数の保存データ要素のうちの前記クエリにより抽出された特定の保存データ要素を前記クエリの結果に含めるかどうかを、当該特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、クエリを処理する装置及び方法に関する。特に、本発明は、ＮｏＳＱＬ型のデータベース（ＮｏＳＱＬデータベース）に対するクエリを処理する装置及び方法に関する。
【背景技術】
【０００２】
トランザクションをサポートしないＮｏＳＱＬデータベース上でトランザクション機能を実現する技術は知られている（例えば、非特許文献１、２参照）。
【０００３】
非特許文献１は、大きいデータセットの逐次的更新処理のためのシステムであるＰｅｒｃｏｌａｔｏｒを開示する。
【０００４】
非特許文献２は、“ｖａｌｕｅ”フィールドを含むモデルに対して、トランザクション中に変更されたオブジェクトのバージョンを表す“ｕｐｄａｔｅｄ”フィールドを追加することを開示する。
【０００５】
尚、トランザクションの状態を管理する技術は、公報記載の技術としても知られている（例えば、特許文献１〜４参照）。
【０００６】
特許文献１は、データベースの更新要求に応答して、更新データにトランザクション毎に異なるコミット情報を付加して記憶し、コミット要求に応答して、コミット対象の更新データからコミット情報を除去し、利用者からの表示要求に応答して、コミットしたデータを検索し、コミット前のデータで、かつ自トランザクションで更新データを検索し、コミット前のデータで、かつ他のトランザクションでの更新データを検索し、これらの検索結果を表示方法を変えて表示装置に出力する技術を開示する。
【０００７】
特許文献２は、データの変更操作の処理は高速な挿入向けデータ保持手段及び削除向けデータ保持手段をそれぞれ複数備え、データ保持部管理手段は、それぞれの挿入向けデータ保持手段又は削除向けデータ保持手段について、対応するトランザクションの識別子とともに、未使用，使用中，コミット済み，転送中の別を保持する技術を開示する。
【０００８】
特許文献３は、キーをグローバル・トランザクションＩＤ、バリューを{トランザクションの状態,終了待ちグローバル・トランザクションＩＤ}とする、管理用マップを用意し、グローバル・トランザクションの開始処理では、管理用マップのキーを管理するサーバ上で、管理用ローカル・トランザクションを開始し、グローバル・トランザクションの終了を待機する処理では、管理用マップのキーを管理するサーバ上で、ロック開放待ち用ローカル・トランザクションを開始し、競合するトランザクションの終了を待機する技術を開示する。
【０００９】
特許文献４は、第１の記憶部は、トランザクションによる更新処理のログを記憶し、第２の記憶部は、更新部によりデータが更新された場合に、データの更新がなされたことを示す更新情報をトランザクションＩＤに対応付けて記憶し、復元部は、検索部により検索された際に、検索対象となるデータの更新情報が、第２の記憶部に存在するか否かを判定し、判定が真の場合に、データを更新したトランザクションを第１の記憶部から読み出し、データの復元処理を行う技術を開示する。
【先行技術文献】
【特許文献】
【００１０】
【特許文献１】特開平５−２８９９２１号公報
【特許文献２】特開２００９−２６３３４号公報
【特許文献３】特開２０１３−３３３４５号公報
【特許文献４】ＷＯ２０１１／０９９０８２号公報
【非特許文献】
【００１１】
【非特許文献１】Large-scale Incremental Processing Using Distributed Transactions and Notifications、［online］、［平成２６年９月１０日検索］、インターネット＜URL：http://research.google.com/pubs/pub36726.html＞
【非特許文献２】MongoDB transaction example、［online］、［平成２６年９月１日検索］、インターネット＜URL：https://github.com/rystsov/mongodb-transaction-example＞
【発明の概要】
【発明が解決しようとする課題】
【００１２】
このように、ＮｏＳＱＬデータベース上でトランザクション機能を実現することは公知であった。しかしながら、非特許文献１の技術は、主キーに対応した値を返す機能を提供するが、条件に合致した値を返すといった複雑なクエリをサポートしていない。また、非特許文献２の技術を普通に用いた場合には、“ｖａｌｕｅ”フィールドのみを対象にクエリを実行することになるだけであり、最新のデータを抽出することはできないという問題があった。
【００１３】
尚、特許文献１〜４の技術は、このような問題に対する解決手段を提示するものではない。
【００１４】
本発明の目的は、ＮｏＳＱＬデータベース上でトランザクション機能を実現し、かつ、最新のデータをクエリで抽出することにある。
【課題を解決するための手段】
【００１５】
かかる目的のもと、本発明は、ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置であって、データベースにおけるコミットされて保存された複数の保存データ要素と、複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部と、複数の未保存データ要素に対して、クエリを実行する第１のクエリ実行部と、第１のクエリ実行部によりクエリが実行された後に、複数の保存データ要素に対して、クエリを実行する第２のクエリ実行部と、第２のクエリ実行部によりクエリが実行された後に、第２のクエリ実行部によるクエリの実行中に保存された少なくとも１つの保存データ要素に対して、クエリを実行する第３のクエリ実行部とを含む、装置を提供する。
【００１６】
ここで、第１のクエリ実行部は、複数の未保存データ要素のうちのクエリにより抽出された特定の未保存データ要素をクエリの結果に含めるかどうかを、特定の未保存データ要素による更新に関するトランザクションの状態に基づいて判定する、ものであってよい。その場合、第１のクエリ実行部は、トランザクションがクエリを実行している場合は、特定の未保存データ要素をクエリの結果に含め、トランザクションがクエリを実行しておらず、トランザクションの状態がコミット済みである場合は、特定の未保存データ要素で、複数の保存データ要素のうちの特定の未保存データ要素による更新の対象である保存データ要素を置き換える、ものであってよい。
【００１７】
また、第２のクエリ実行部は、複数の保存データ要素のうちのクエリにより抽出された特定の保存データ要素をクエリの結果に含めるかどうかを、特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、ものであってもよい。その場合、第２のクエリ実行部は、特定の保存データ要素の更新のための未保存データ要素が記憶されていない場合、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態がアボートである場合、及び、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態が実行中であり、トランザクションがクエリを実行していない場合は、特定の保存データ要素をクエリの結果に含め、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態がコミット済みである場合は、特定の未保存データ要素で特定の保存データ要素を置き換える、ものであってよい。
【００１８】
更に、第３のクエリ実行部は、少なくとも１つの保存データ要素のうちのクエリにより抽出された特定の保存データ要素をクエリの結果に含めるかどうかを、特定の保存データ要素の更新に関するトランザクションの状態に基づいて判定する、ものであってよい。その場合、第３のクエリ実行部は、特定の保存データ要素の更新のための未保存データ要素が記憶されていない場合、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態がアボートである場合、及び、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態が実行中である場合は、特定の保存データ要素をクエリの結果に含め、特定の保存データ要素の更新のための特定の未保存データ要素が記憶されており、トランザクションの状態がコミット済みである場合は、特定の未保存データ要素で特定の保存データ要素を置き換えた後、第３のクエリ実行部の処理を再実行する、ものであってよい。
【００１９】
更にまた、記憶部は、複数の未保存データ要素の各未保存データ要素に関連付けて、各未保存データ要素による更新を実行したトランザクションを識別するトランザクションＩＤを記憶する、ものであってよい。その場合、記憶部は、複数の保存データ要素の各保存データ要素、各未保存データ要素、及びトランザクションＩＤを１つのエントリとして記憶する、ものであってよい。また、記憶部は、トランザクションの状態を示すトランザクション状態情報をトランザクションＩＤに関連付けて記憶する、ものであってよい。第１のクエリ実行部、第２のクエリ実行部、及び第３のクエリ実行部は、それぞれ、クエリにより抽出されたデータ要素を含むエントリ中のトランザクションＩＤによりトランザクション状態情報を参照しながら処理を実行する、ものであってよい。第２のクエリ実行部は、クエリにより抽出された保存データ要素にエントリ中で付随する未保存データ要素がコミット済みのトランザクションにより更新されていた場合は、未保存データ要素で保存データ要素を置き換えて、エントリに関連するキーを保存し、第３のクエリ実行部は、キーを用いてクエリを実行する、ものであってよい。
【００２０】
また、本発明は、ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置であって、データベースにおけるコミットされて保存された複数の保存データ要素と、複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素と、複数の保存データ要素の複数の未保存データ要素による更新に関する複数のトランザクションを識別する複数の識別情報とを対応付けて記憶する記憶部と、複数の未保存データ要素に対して、クエリを実行し、複数の未保存データ要素のうちのクエリにより抽出された特定の未保存データ要素を、複数の識別情報のうちの特定の未保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、クエリの結果に含める第１のクエリ実行部と、第１のクエリ実行部によりクエリが実行された後に、複数の保存データ要素に対して、クエリを実行し、複数の保存データ要素のうちのクエリにより抽出された特定の保存データ要素を、複数の識別情報のうちの特定の保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、クエリの結果に含める第２のクエリ実行部と、第２のクエリ実行部によりクエリが実行された後に、第２のクエリ実行部によるクエリの実行中に保存された少なくとも１つの保存データ要素に対して、クエリを実行し、少なくとも１つの保存データ要素のうちのクエリにより抽出された特定の保存データ要素を、複数の識別情報のうちの特定の保存データ要素と対応付けて記憶された識別情報により識別されるトランザクションの状態が所定の条件を満たす場合に、クエリの結果に含める第３のクエリ実行部とを含む、装置も提供する。
【００２１】
更に、本発明は、ＮｏＳＱＬ型のデータベースに対するクエリを処理する方法であって、データベースにおけるコミットされて保存された複数の保存データ要素と、複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部を含み、複数の未保存データ要素に対して、クエリを実行する第１のステップと、第１のステップでクエリが実行された後に、複数の保存データ要素に対して、クエリを実行する第２のステップと、第２のステップでクエリが実行された後に、第２のステップでのクエリの実行中に保存された少なくとも１つの保存データ要素に対して、クエリを実行する第３のステップとを含む、方法も提供する。
【００２２】
更にまた、本発明は、ＮｏＳＱＬ型のデータベースに対するクエリを処理する装置として、コンピュータを機能させるプログラムであって、コンピュータを、データベースにおけるコミットされて保存された複数の保存データ要素と、複数の保存データ要素の更新のための、コミットされていない又はコミットされたが保存されていない複数の未保存データ要素とを記憶する記憶部と、複数の未保存データ要素に対して、クエリを実行する第１のクエリ実行部と、第１のクエリ実行部によりクエリが実行された後に、複数の保存データ要素に対して、クエリを実行する第２のクエリ実行部と、第２のクエリ実行部によりクエリが実行された後に、第２のクエリ実行部によるクエリの実行中に保存された少なくとも１つの保存データ要素に対して、クエリを実行する第３のクエリ実行部として機能させる、プログラムも提供する。
【発明の効果】
【００２３】
本発明によれば、ＮｏＳＱＬデータベース上でトランザクション機能を実現し、かつ、最新のデータをクエリで抽出することができる。
【図面の簡単な説明】
【００２４】
【図１】（ａ）〜（ｆ）は、コミット済みデータのみに対してクエリを実行したときの様子を示した図である。
【図２】（ａ）〜（ｆ）は、インフライトデータに対してクエリを実行する第１フェーズにおける処理の様子を示した図である。
【図３】（ａ）〜（ｆ）は、コミット済みデータに対してクエリを実行する第２フェーズにおける処理の様子を示した図である。
【図４】（ａ）〜（ｆ）は、第２フェーズで保存されたキーに対応するコミット済みデータに対して再度第２フェーズと同じクエリを実行する第３フェーズにおける処理の様子を示した図である。
【図５】本発明の実施の形態におけるデータベース装置の機能構成例を示した図である。
【図６】本実施の形態におけるクエリ処理部の第１フェーズの動作例を示したフローチャートである。
【図７】本実施の形態におけるクエリ処理部の第２フェーズの動作例を示したフローチャートである。
【図８】本実施の形態におけるクエリ処理部の第３フェーズの動作例を示したフローチャートである。
【図９】本発明の実施の形態におけるデータベース装置のハードウェア構成例を示した図である。
【発明を実施するための形態】
【００２５】
以下、添付図面を参照して、本発明の実施の形態について詳細に説明する。
【００２６】
［本実施の形態の背景］
１つのエントリに対する原子的な更新のみを保障するＮｏＳＱＬデータベースにおいても、複数のエントリに対する原子的な更新を行うトランザクションは実現可能である。「実行中」、「コミット済み」、「アボート」等のトランザクション状態と、コミットされていない又はコミットされているがコミット済みデータとして保存されていないデータ（以下、「インフライトデータ」という）とを、ＮｏＳＱＬデータベース内に保存することにより、既存のＮｏＳＱＬデータベースを変更せずに、トランザクションは実現できる。
【００２７】
具体的には、以下のようなステップを実行すればよい。即ち、第１ステップは、トランザクションの開始時に、トランザクションを識別するトランザクションＩＤに対して、トランザクション状態「実行中」を保存するステップである。第２ステップは、トランザクションが更新で用いるデータを、インフライトデータとして、トランザクションＩＤと共にＮｏＳＱＬデータベースに保存するステップである。第３ステップは、トランザクションのコミット時に、トランザクションＩＤに対するトランザクション状態を「コミット済み」で上書きするステップである。第４ステップは、インフライトデータをコミット済みデータとして保存するステップである。
【００２８】
このようなＮｏＳＱＬデータベースに対してクエリを実行することで最新のデータを抽出することを考える。但し、クエリは、以下のようなものとする。即ち、第一に、ジョイン処理をサポートしないものとする。つまり、複数のエントリの関連を指定するクエリは存在しない。また、第二に、キー以外も指定したクエリをサポートするものとする。つまり、ＫＶＳ（Key-Value Store）以上のクエリが実行可能である。
【００２９】
例えば、ＭｏｎｇｏＤＢは、コミット済みデータのみを対象にクエリを実行する機能を提供する。しかしながら、上述したようにインフライトデータがＮｏＳＱＬデータベースに保存された状態では、インフライトデータをトランザクション状態に応じて処理する必要がある。ところが、インフライトデータは、コミットされたとしても、クライアントの障害等により、コミット済みデータとして保存されない可能性がある。つまり、上記の第４ステップは実行されない場合がある。このような場合、インフライトデータについて、コミットされていないのか、コミットされたがコミット済みデータとして保存されていないのか、判断できない。従って、コミットされたがコミット済みデータとして保存されていないデータはクエリにより抽出できない。こうしたことから、インフライトデータがＮｏＳＱＬデータベースに保存された状態では、ＭｏｎｇｏＤＢが提供するクエリ機能は利用できなくなってしまう。
【００３０】
図１（ａ）〜（ｆ）は、コミット済みデータのみに対してクエリを実行したときの様子を示した図である。ここで、各エントリにおいて、「＿ｉｄ」はキーを表し、これに続く「ｖａｌｕｅ１」「ｖａｌｕｅ２」はコミット済みデータを表す。そして、これに続く「＿ｄｉｒｔｙ」の後において、「ｖａｌｕｅ１」「ｖａｌｕｅ２」はインフライトデータを表し、「＿ｔｘＩｄ」はトランザクションＩＤを表す。また、トランザクションＩＤ「Ｔｘ１」に対してトランザクション状態「実行中」が、トランザクションＩＤ「Ｔｘ２」に対してトランザクション状態「コミット済み」が、トランザクションＩＤ「Ｔｘ３」に対してトランザクション状態「アボート」が、それぞれ保持されているものとする。そして、図には、トランザクション「Ｔｘ」がクエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝を実行したときの様子を示す。
【００３１】
尚、本明細書において、クエリは、ＭｏｎｇｏＤＢクエリ言語の記法に従って記述する。即ち、｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝は、コミット済みデータにおけるｖａｌｕｅ１の値が「０」より大きいエントリ（太枠で囲んで示す）を抽出することを意味する。
【００３２】
図１（ａ）では、エントリ３０ａにトランザクションＩＤ「Ｔｘ１」が保持されており、このトランザクションＩＤに対してトランザクション状態「実行中」が保持されている。従って、最新のデータはコミット済みデータであり、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ａはクエリ結果に含まれるはずである。一方で、コミット済みデータのみに対してクエリを実行した場合も、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ａはクエリ結果に含まれる。従って、このエントリ３０ａについては、クエリ結果に問題は生じていない。
【００３３】
図１（ｂ）では、エントリ３０ｂにトランザクションＩＤ「Ｔｘ２」が保持されており、このトランザクションＩＤに対してトランザクション状態「コミット済み」が保持されている。従って、最新のデータはインフライトデータであり、インフライトデータにおけるｖａｌｕｅ１の値「−５」は「０」より大きくないので、エントリ３０ｂはクエリ結果に含まれないはずである。一方で、コミット済みデータのみに対してクエリを実行した場合は、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ｂはクエリ結果に含まれる。従って、このエントリ３０ｂについては、トランザクションがコミットしたはずのデータがクエリ結果に反映されないという問題が生じている。
【００３４】
図１（ｃ）では、エントリ３０ｃにトランザクションＩＤ「Ｔｘ２」が保持されており、このトランザクションＩＤに対してトランザクション状態「コミット済み」が保持されている。従って、最新のデータはインフライトデータであり、インフライトデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ｃはクエリ結果に含まれるはずである。一方で、コミット済みデータのみに対してクエリを実行した場合は、コミット済みデータにおけるｖａｌｕｅ１の値「−１０」は「０」より大きくないので、エントリ３０ｃはクエリ結果に含まれない。従って、このエントリ３０ｃについては、トランザクションがコミットしたはずのデータがクエリ結果に反映されないという問題が生じている。
【００３５】
図１（ｄ）では、エントリ３０ｄにトランザクションＩＤ「Ｔｘ３」が保持されており、このトランザクションＩＤに対してトランザクション状態「アボート」が保持されている。従って、最新のデータはコミット済みデータであり、コミット済みデータにおけるｖａｌｕｅ１の値「０」は「０」より大きくないので、エントリ３０ｄはクエリ結果に含まれないはずである。一方で、コミット済みデータのみに対してクエリを実行した場合も、コミット済みデータにおけるｖａｌｕｅ１の値「０」は「０」より大きくないので、エントリ３０ｄはクエリ結果に含まれない。従って、このエントリ３０ｄについては、クエリ結果に問題は生じていない。
【００３６】
図１（ｅ）では、エントリ３０ｅにトランザクションＩＤ「Ｔｘ」が保持されており、このトランザクションＩＤのトランザクションはクエリを実行しているトランザクションである。従って、最新のデータはインフライトデータであり、インフライトデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ｅはクエリ結果に含まれるはずである。一方で、コミット済みデータのみに対してクエリを実行した場合は、コミット済みデータにおけるｖａｌｕｅ１の値「０」は「０」より大きくないので、エントリ３０ｅはクエリ結果に含まれない。従って、このエントリ３０ｅについては、クエリを実行しているトランザクションが更新したデータがクエリ結果に反映されないという問題が生じている。
【００３７】
図１（ｆ）では、エントリ３０ｆにトランザクションＩＤ「Ｔｘ３」が保持されており、このトランザクションＩＤに対してトランザクション状態「アボート」が保持されている。従って、最新のデータはコミット済みデータであり、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ｆはクエリ結果に含まれるはずである。一方で、コミット済みデータのみに対してクエリを実行した場合も、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３０ｆはクエリ結果に含まれる。従って、このエントリ３０ｆについては、クエリ結果に問題は生じていない。
【００３８】
［本実施の形態の概要］
そこで、本実施の形態では、クエリを実行した時刻で最新のデータ、又は、その時刻以降に最新となったデータを、クエリ結果として返す。そのために、原子的な更新が可能なエントリごとにコミット済みデータ（Committed Data）とインフライトデータ（In-Flight Data）とを保持し、インフライトデータ、コミット済みデータ、クエリ実行中にコミットされ保存されたデータをこの順に対象としてクエリを実行する。以下、これらの各データを対象としたクエリの実行を、第１フェーズ、第２フェーズ、第３フェーズとし、図１（ａ）〜（ｆ）と略同様の例を用いて説明する。
【００３９】
第１フェーズは、インフライトデータに対してクエリを実行するフェーズである。このフェーズでは、クエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝は、プレフィックス「＿ｄｉｒｔｙ」が付加されることにより、クエリ｛＿ｄｉｒｔｙ．ｖａｌｕｅ１：｛＄ｇｔ：０｝｝に変換され、この変換後のクエリが実行される。
【００４０】
図２（ａ）〜（ｆ）は、このときの処理の様子を示した図である。第１フェーズでは、まず、上記の変換後のクエリにより、インフライトデータにおけるｖａｌｕｅ１の値が「０」より大きいエントリが抽出される。図では、ここで抽出されたエントリを太線で囲んで示している。
【００４１】
即ち、図２（ａ）のエントリ３１ａのインフライトデータにおけるｖａｌｕｅ１の値「０」、図２（ｂ）のエントリ３１ｂのインフライトデータにおけるｖａｌｕｅ１の値「−５」、及び、図２（ｆ）のエントリ３１ｆのインフライトデータにおけるｖａｌｕｅ１の値「−１０」は何れも「０」より大きくないので、エントリ３１ａ，３１ｂ，３１ｆは抽出されない。
【００４２】
一方、図２（ｃ）のエントリ３１ｃのインフライトデータにおけるｖａｌｕｅ１の値「１０」、図２（ｄ）のエントリ３１ｄのインフライトデータにおけるｖａｌｕｅ１の値「１０」、及び、図２（ｅ）のエントリ３１ｅのインフライトデータにおけるｖａｌｕｅ１の値「１０」は何れも「０」より大きいので、エントリ３１ｃ，３１ｄ，３１ｅは抽出される。そして、この抽出されたエントリ３１ｃ，３１ｄ，３１ｅに対して、トランザクション状態に応じた処理が行われる。
【００４３】
図２（ｅ）では、エントリ３１ｅにトランザクションＩＤ「Ｔｘ」が保持されており、このトランザクションＩＤのトランザクションはクエリを実行しているトランザクションである。従って、エントリ３１ｅにおけるインフライトデータは、最新のデータであり、クエリ結果に追加される。
【００４４】
図２（ｃ）では、エントリ３１ｃにトランザクションＩＤ「Ｔｘ２」が保持されており、このトランザクションＩＤに対してトランザクション状態「コミット済み」が保持されている。従って、エントリ３１ｃにおけるインフライトデータは、コミット済みデータに変換される。
【００４５】
図２（ｄ）では、エントリ３１ｄにトランザクションＩＤ「Ｔｘ３」が保持されており、このトランザクションＩＤに対してトランザクション状態「アボート」が保持されている。従って、エントリ３１ｄにおけるインフライトデータは、最新のデータでなく、クエリ結果に追加されない。
【００４６】
第２フェーズは、コミット済みデータに対してクエリを実行するフェーズである。このフェーズでは、クエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝がそのまま実行される。
【００４７】
図３（ａ）〜（ｆ）は、このときの処理の様子を示した図である。第２フェーズでは、まず、上記のクエリにより、コミット済みデータにおけるｖａｌｕｅ１の値が「０」より大きいエントリが抽出される。図では、ここで抽出されたエントリを太線で囲んで示している。
【００４８】
即ち、図３（ｄ）のエントリ３２ｄのコミット済みデータにおけるｖａｌｕｅ１の値「０」は「０」より大きくないので、エントリ３２ｄは抽出されない。
【００４９】
一方、図３（ａ）のエントリ３２ａのコミット済みデータにおけるｖａｌｕｅ１の値「１０」、図３（ｂ）のエントリ３２ｂのコミット済みデータにおけるｖａｌｕｅ１の値「３０」、図３（ｅ）のエントリ３２ｅのコミット済みデータにおけるｖａｌｕｅ１の値「５」、及び、図３（ｆ）のエントリ３２ｆのコミット済みデータにおけるｖａｌｕｅ１の値「１０」は何れも「０」より大きいので、エントリ３２ａ，３２ｂ，３２ｅ，３２ｆは抽出される。また、図３（ｃ）のエントリ３２ｃのコミット済みデータは、図２（ｃ）のエントリ３１ｃのインフライトデータで置き換えられており、コミット済みデータにおけるｖａｌｕｅ１の値「１０」は「０」より大きいので、エントリ３２ｃも抽出される。そして、この抽出されたエントリ３２ａ，３２ｂ，３２ｃ，３２ｅ，３２ｆに対して、トランザクション状態に応じた処理が行われる。
【００５０】
図３（ｃ）では、エントリ３２ｃにインフライトデータが保持されていない。従って、エントリ３２ｃにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００５１】
図３（ｅ）では、エントリ３２ｅにトランザクションＩＤ「Ｔｘ」が保持されており、このトランザクションＩＤのトランザクションはクエリを実行しているトランザクションである。従って、このトランザクションＩＤに対してトランザクション状態「実行中」が保持されているが、エントリ３２ｅにおけるコミット済みデータは、最新のデータでなく、クエリ結果に追加されない。
【００５２】
図３（ｂ）では、エントリ３２ｂにトランザクションＩＤ「Ｔｘ２」が保持されており、このトランザクションＩＤに対してトランザクション状態「コミット済み」が保持されている。従って、エントリ３２ｂにおけるインフライトデータは、コミット済みデータに変換され、エントリ３２ｂのキーが保存される。
【００５３】
図３（ｆ）では、エントリ３２ｆにトランザクションＩＤ「Ｔｘ３」が保持されており、このトランザクションＩＤに対してトランザクション状態「アボート」が保持されている。従って、エントリ３２ｆにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００５４】
図３（ａ）では、エントリ３２ａにトランザクションＩＤ「Ｔｘ１」が保持されており、このトランザクションＩＤに対してトランザクション状態「実行中」が保持されている。また、このトランザクションＩＤのトランザクションはクエリを実行しているトランザクションでない。従って、エントリ３２ａにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００５５】
第３フェーズは、第２フェーズで保存されたキーに対応するコミット済みデータに対して、再度第２フェーズと同じクエリを実行するフェーズである。このフェーズでは、クエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝は、もう１つの条件「＿ｉｄ：｛＄ｉｎ，［ｋ２］｝」が追加されることより、クエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝，＿ｉｄ：｛＄ｉｎ，［ｋ２］｝｝に変換され、この変換後のクエリが実行される。尚、２つ目の条件「＿ｉｄ：｛＄ｉｎ，［ｋ２］｝」は、「＿ｉｄ」の値が［］内に列挙された値に含まれるという条件を意味する。
【００５６】
図４（ａ）〜（ｆ）は、このときの処理の様子を示した図である。第３フェーズでは、上記のクエリの２つ目の条件により、図４（ｂ）のエントリ３３ｂのみが対象となる。図では、このことを図４（ａ），（ｃ）〜（ｆ）のエントリを破線で囲むことにより示している。しかしながら、図４（ｂ）のエントリ３３ｂのコミット済みデータにおけるｖａｌｕｅ１の値「−５」は「０」より大きくないので、結局、エントリ３３ｂは抽出されないこととなる。
【００５７】
そこで、仮に、上記のクエリの２つ目の条件を「＿ｉｄ：｛＄ｉｎ，［ｋ１，ｋ２，ｋ３，ｋ４，ｋ６］｝」とし、この条件により、図３（ａ）〜（ｄ），（ｆ）のエントリ３２ａ〜３２ｄ，３２ｆが第３フェーズにおける処理の対象になったものとする。尚、このときは、第２フェーズのクエリ実行時に、図３（ａ）〜（ｄ），（ｆ）のエントリ３２ａ〜３２ｄ，３２ｆの全てにおいて、インフライトデータはコミット済みデータに変換されているはずである。しかしながら、その後のトランザクションの処理により再び図３（ａ），（ｂ），（ｄ），（ｆ）のようにインフライトデータが保持されることはあり得る。また、上記のクエリの２つ目の条件でｋ５を除いたのは、クエリを実行しているトランザクションのコミット後に同じトランザクションがインフライトデータを生成することはないからである。以下、図３（ａ）〜（ｄ），（ｆ）のエントリ３２ａ〜３２ｄ，３２ｆを対象として、第３フェーズについて説明する。
【００５８】
第３フェーズでは、まず、上記のクエリにより、コミット済みデータにおけるｖａｌｕｅ１の値が「０」より大きいエントリが抽出される。ここでも、太線で囲んで示したエントリが、抽出されるエントリである。
【００５９】
即ち、図３（ｄ）のエントリ３２ｄのコミット済みデータにおけるｖａｌｕｅ１の値「０」は「０」より大きくないので、エントリ３２ｄは抽出されない。
【００６０】
一方、図３（ａ）のエントリ３２ａのコミット済みデータにおけるｖａｌｕｅ１の値「１０」、図３（ｂ）のエントリ３２ｂのコミット済みデータにおけるｖａｌｕｅ１の値「３０」、図３（ｃ）のエントリ３２ｃのコミット済みデータにおけるｖａｌｕｅ１の値「１０」、及び、図３（ｆ）のエントリ３２ｆのコミット済みデータにおけるｖａｌｕｅ１の値「１０」は何れも「０」より大きいので、エントリ３２ａ，３２ｂ，３２ｃ，３２ｆは抽出される。そして、この抽出されたエントリ３２ａ，３２ｂ，３２ｃ，３２ｆに対して、トランザクション状態に応じた処理が行われる。
【００６１】
図３（ｃ）では、エントリ３２ｃにインフライトデータが保持されていない。従って、エントリ３２ｃにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００６２】
図３（ｂ）では、エントリ３２ｂにトランザクションＩＤ「Ｔｘ２」が保持されており、このトランザクションＩＤに対してトランザクション状態「コミット済み」が保持されている。従って、エントリ３２ｂにおけるインフライトデータは、コミット済みデータに変換され、エントリ３２ｂのキーが保存される。そして、このエントリ３２ｂについて、第３フェーズが再実行される。
【００６３】
図３（ｆ）では、エントリ３２ｆにトランザクションＩＤ「Ｔｘ３」が保持されており、このトランザクションＩＤに対してトランザクション状態「アボート」が保持されている。従って、エントリ３２ｆにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００６４】
図３（ａ）では、エントリ３２ａにトランザクションＩＤ「Ｔｘ１」が保持されており、このトランザクションＩＤに対してトランザクション状態「実行中」が保持されている。従って、エントリ３２ａにおけるコミット済みデータは、最新のデータであり、クエリ結果に追加される。
【００６５】
［本実施の形態におけるデータベース装置の機能構成］
図５は、本実施の形態におけるデータベース装置１０の機能構成例を示した図である。図示するように、このデータベース装置１０は、クエリ処理部２０と、データベース部３０とを含む。そして、クエリ処理部２０は、クエリ受付部２１と、第１クエリ実行部２２と、第２クエリ実行部２３と、第３クエリ実行部２４と、キー記憶部２５と、クエリ結果記憶部２６と、クエリ結果出力部２７とを含む。また、データベース部３０は、データ記憶部３１と、トランザクション状態記憶部３２とを含む。
【００６６】
まず、クエリ処理部２０の構成要素について説明する。
【００６７】
クエリ受付部２１は、例えばクライアントが発行したクエリを受け付ける。
【００６８】
第１クエリ実行部２２は、クエリ受付部２１が受け付けたクエリを、データ記憶部３１における対象のエントリに保持されたインフライトデータに対して実行する。そして、各エントリを更新中のトランザクションとクエリを実行しているトランザクションとが同じかどうか、及び、トランザクション状態記憶部３２に記憶された各エントリに対するトランザクション状態に基づいて、クエリ結果を求め、これをクエリ結果記憶部２６に記憶する。その際、あるエントリに対するトランザクション状態が「コミット済み」であれば、そのエントリに保持されたインフライトデータをコミット済みデータに変換する。本実施の形態では、コミットされていない又はコミットされたが保存されていない未保存データ要素の一例として、インフライトデータを用いており、複数の未保存データ要素に対してクエリを実行する第１のクエリ実行部の一例として、第１クエリ実行部２２を設けている。
【００６９】
第２クエリ実行部２３は、クエリ受付部２１が受け付けたクエリを、データ記憶部３１における対象のエントリに保持されたコミット済みデータに対して実行する。そして、各エントリを更新中のトランザクションがあるかどうか、各エントリを更新中のトランザクションとクエリを実行しているトランザクションとが同じかどうか、及び、トランザクション状態記憶部３２に記憶された各エントリに対するトランザクション状態に基づいて、クエリ結果を求め、これをクエリ結果記憶部２６に記憶する。その際、あるエントリに対するトランザクション状態が「コミット済み」であれば、そのエントリに保持されたインフライトデータをコミット済みデータに変換し、そのエントリのキーをキー記憶部２５に記憶する。本実施の形態では、コミットされて保存された保存データ要素の一例として、コミット済みデータを用いており、複数の保存データ要素に対してクエリを実行する第２のクエリ実行部の一例として、第２クエリ実行部２３を設けている。
【００７０】
第３クエリ実行部２４は、キー記憶部２５にキーが記憶されているかどうかを判定する。そして、キー記憶部２５にキーが記憶されていれば、クエリ受付部２１が受け付けたクエリを、そのキーを保持するエントリに保持されたコミット済みデータに対して実行し、その後、第２クエリ実行部２３と同様の処理を行う。また、キー記憶部２５にキーが記憶されていなければ、処理が終了した旨をクエリ結果出力部２７に通知する。本実施の形態では、第２のクエリ実行部によるクエリの実行中に保存された少なくとも１つの保存データ要素の一例として、キーを保持するエントリに保持されたコミット済みデータを用いており、少なくとも１つの保存データ要素に対してクエリを実行する第３のクエリ実行部の一例として、第３クエリ実行部２４を設けている。
【００７１】
キー記憶部２５は、第２クエリ実行部２３又は第３クエリ実行部２４があるエントリに保持されたインフライトデータをコミット済みデータに変換した場合に第２クエリ実行部２３又は第３クエリ実行部２４から渡され、第３クエリ実行部２４により読み出されるそのエントリのキーを記憶する。
【００７２】
クエリ結果記憶部２６は、第１クエリ実行部２２により求められたクエリ結果と、第２クエリ実行部２３により求められたクエリ結果と、第３クエリ実行部２４により求められたクエリ結果とを記憶する。
【００７３】
クエリ結果出力部２７は、第３クエリ実行部２４から処理が終了した旨を通知されると、クエリ結果記憶部２６に記憶されたクエリ結果を外部に出力する。
【００７４】
次に、データベース部３０の構成要素について説明する。
【００７５】
データ記憶部３１は、クエリ処理部２０によるクエリ処理の対象となるデータを記憶する。具体的には、データとしてエントリを記憶し、各エントリには、上述したように、キーとコミット済みデータとインフライトデータとトランザクションＩＤとを保持する。本実施の形態では、複数の保存データ要素と複数の未保存データ要素とを記憶する記憶部の一例として、データ記憶部３１を設けている。
【００７６】
トランザクション状態記憶部３２は、トランザクションＩＤとそのトランザクションＩＤで識別されるトランザクションの状態であるトランザクション状態とを対応付けて記憶する。ここで、トランザクション状態には、上述したように、「実行中」、「コミット済み」、「アボート」等がある。
【００７７】
［本実施の形態におけるクエリ処理部の動作］
図６は、本実施の形態におけるクエリ処理部２０の第１フェーズの動作例を示したフローチャートである。クエリ処理部２０では、上述したように、第１クエリ実行部２２が第１フェーズの動作を行う。尚、この動作に先立ち、クエリ受付部２１が、例えばクライアントが発行したクエリを受け付けるものとする。図２（ａ）〜（ｆ）の例で言えば、クエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝を受け付ける。そして、クエリ受付部２１が、受け付けたクエリを第１クエリ実行部２２に受け渡すことにより、この動作は開始する。
【００７８】
動作が開始すると、まず、第１クエリ実行部２２は、インフライトデータに対してクエリを実行する（ステップ２０１）。図２（ａ）〜（ｆ）の例で言えば、クエリ受付部２１から受け取ったクエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝をクエリ｛＿ｄｉｒｔｙ．ｖａｌｕｅ１：｛＄ｇｔ：０｝｝に変換する。そして、この変換後のクエリをデータ記憶部３１に記憶されたエントリに対して実行する。その際、第１クエリ実行部２２は、エントリに対するカーソルを取得する。
【００７９】
次に、第１クエリ実行部２２は、このカーソルが次のエントリを有するかどうかを判定する（ステップ２０２）。そして、このカーソルが次のエントリを有すると判定すれば、データ記憶部３１から、そのエントリを取得する（ステップ２０３）。次いで、第１クエリ実行部２２は、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中であるかどうかを判定する（ステップ２０４）。ここで、この判定は、別途保持されているクエリを実行中のトランザクションのトランザクションＩＤと、エントリに保持されているトランザクションＩＤとを比較することにより、行えばよい。
【００８０】
その結果、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中であると判定すれば、第１クエリ実行部２２は、そのエントリに保持されているインフライトデータをクエリ結果記憶部２６のクエリ結果に追加し（ステップ２０５）、処理をステップ２０２へ戻す。図２（ａ）〜（ｆ）の例で言えば、図２（ｅ）のエントリ３１ｅに保持されているインフライトデータをクエリ結果に追加する。
【００８１】
一方、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中でないと判定すれば、第１クエリ実行部２２は、そのエントリに対するトランザクション状態を確認する（ステップ２０６）。ここで、この確認は、そのエントリに保持されているトランザクションＩＤに対するトランザクション状態をトランザクション状態記憶部３２から取得することにより、行えばよい。
【００８２】
これにより、第１クエリ実行部２２は、インフライトデータがロールバックされるかどうかを判定する（ステップ２０７）。インフライトデータがロールバックされると判定すれば、第１クエリ実行部２２は、そのまま処理をステップ２０２へ戻す。図２（ａ）〜（ｆ）の例で言えば、図２（ｄ）のエントリ３１ｄに保持されているインフライトデータはクエリ結果に追加しない。或いは、図６には示していないが、第１クエリ実行部２２が、エントリからインフライトデータを削除する処理を行った後に、処理をステップ２０２へ戻してもよい。
【００８３】
一方、インフライトデータがロールバックされると判定しなければ、第１クエリ実行部２２は、インフライトデータがコミットされたかどうかを判定する（ステップ２０８）。インフライトデータがコミットされたと判定すれば、第１クエリ実行部２２は、このインフライトデータでコミット済みデータを置き換え（ステップ２０９）、処理をステップ２０２へ戻す。図２（ａ）〜（ｆ）の例で言えば、図２（ｃ）のエントリ３１ｃに保持されているインフライトデータをコミット済みデータに変換する。一方、インフライトデータがコミットされていないと判定すれば、第１クエリ実行部２２は、そのまま処理をステップ２０２へ戻す。
【００８４】
その後、ステップ２０２でこのカーソルが次のエントリを有しないと判定すれば、第２フェーズの動作に移る。具体的には、第１クエリ実行部２２が、第１フェーズの動作の開始時にクエリ受付部２１から受け取ったクエリを第２クエリ実行部２３に受け渡す。
【００８５】
図７は、本実施の形態におけるクエリ処理部２０の第２フェーズの動作例を示したフローチャートである。クエリ処理部２０では、上述したように、第２クエリ実行部２３が第２フェーズの動作を行う。尚、第１クエリ実行部２２が、第１フェーズの動作の開始時にクエリ受付部２１から受け取ったクエリを第２クエリ実行部２３に受け渡すことにより、この動作は開始する。
【００８６】
動作が開始すると、まず、第２クエリ実行部２３は、コミット済みデータに対してクエリを実行する（ステップ２２１）。図３（ａ）〜（ｆ）の例で言えば、クエリ受付部２１から受け取ったクエリ｛ｖａｌｕｅ１：｛＄ｇｔ：０｝｝をそのままデータ記憶部３１に記憶されたエントリに対して実行する。その際、第２クエリ実行部２３は、エントリに対するカーソルを取得する。
【００８７】
次に、第２クエリ実行部２３は、このカーソルが次のエントリを有するかどうかを判定する（ステップ２２２）。そして、このカーソルが次のエントリを有すると判定すれば、データ記憶部３１から、そのエントリを取得する（ステップ２２３）。次いで、第２クエリ実行部２３は、そのエントリが、何らかのトランザクションにより更新中であるかどうかを判定する（ステップ２２４）。ここで、この判定は、エントリにインフライトデータが保持されているかどうかを調べることにより、行えばよい。
【００８８】
その結果、そのエントリが、何らかのトランザクションにより更新中でないと判定すれば、第２クエリ実行部２３は、そのエントリに保持されているコミット済みデータをクエリ結果記憶部２６のクエリ結果に追加し（ステップ２２５）、処理をステップ２２２へ戻す。図３（ａ）〜（ｆ）の例で言えば、図３（ｃ）のエントリ３２ｃに保持されているコミット済みデータをクエリ結果に追加する。
【００８９】
一方、そのエントリが、何らかのトランザクションにより更新中であると判定すれば、第２クエリ実行部２３は、そのエントリに対するトランザクション状態を確認する（ステップ２２６）。ここで、この確認は、そのエントリに保持されているトランザクションＩＤに対するトランザクション状態をトランザクション状態記憶部３２から取得することにより、行えばよい。
【００９０】
これにより、第２クエリ実行部２３は、インフライトデータがロールバックされるかどうかを判定する（ステップ２２７）。インフライトデータがロールバックされると判定すれば、第２クエリ実行部２３は、そのエントリに保持されているコミット済みデータをクエリ結果記憶部２６のクエリ結果に追加し（ステップ２２５）、処理をステップ２２２へ戻す。図３（ａ）〜（ｆ）の例で言えば、図３（ｆ）のエントリ３２ｆに保持されているコミット済みデータをクエリ結果に追加する。
【００９１】
一方、インフライトデータがロールバックされると判定しなければ、第２クエリ実行部２３は、インフライトデータがコミットされたかどうかを判定する（ステップ２２８）。インフライトデータがコミットされたと判定すれば、第２クエリ実行部２３は、このインフライトデータでコミット済みデータを置き換え、このエントリのキーをキー記憶部２５に記憶し（ステップ２２９）、処理をステップ２２２へ戻す。図３（ａ）〜（ｆ）の例で言えば、図３（ｂ）のエントリ３２ｂに保持されているインフライトデータをコミット済みデータに変換し、キーｋ２を記憶する。
【００９２】
一方、インフライトデータがコミットされていないと判定すれば、第２クエリ実行部２３は、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中であるかどうかを判定する（ステップ２３０）。ここで、この判定は、別途保持されているクエリを実行中のトランザクションのトランザクションＩＤと、エントリに保持されているトランザクションＩＤとを比較することにより、行えばよい。
【００９３】
その結果、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中でないと判定すれば、第２クエリ実行部２３は、そのエントリに保持されているコミット済みデータをクエリ結果記憶部２６のクエリ結果に追加し（ステップ２２５）、処理をステップ２２２へ戻す。図３（ａ）〜（ｆ）の例で言えば、図３（ａ）のエントリ３２ａに保持されているコミット済みデータをクエリ結果に追加する。
【００９４】
一方、そのエントリが、クエリを実行しているトランザクションと同じトランザクションにより更新中であると判定すれば、第２クエリ実行部２３は、そのまま処理をステップ２２２へ戻す。図３（ａ）〜（ｆ）の例で言えば、図３（ｅ）のエントリ３２ｅに保持されているコミット済みデータはクエリ結果に追加しない。
【００９５】
その後、ステップ２２２でこのカーソルが次のエントリを有しないと判定すれば、第３フェーズの動作に移る。具体的には、第２クエリ実行部２３が、第２フェーズの動作の開始時に第１クエリ実行部２２から受け取ったクエリを第３クエリ実行部２４に受け渡す。
【００９６】
図８は、本実施の形態におけるクエリ処理部２０の第３フェーズの動作例を示したフローチャートである。クエリ処理部２０では、上述したように、第３クエリ実行部２４が第３フェーズの動作を行う。尚、第２クエリ実行部２３が、第２フェーズの動作の開始時に第１クエリ実行部２２から受け取ったクエリを第３クエリ実行部２４に受け渡すことにより、この動作は開始する。
【００９７】
動作が開始すると、まず、第３クエリ実行部２４は、キー記憶部２５にキーが記憶されているかどうかを判定する（ステップ２４１）。
【００９８】
その結果、キー記憶部２５にキーが記憶されていると判定すれば、第３クエリ実行部２４は、そのキーを保持するエントリに対してクエリを実行する（ステップ２４２）。その際、第３クエリ実行部２４は、エントリに対するカーソルを取得する。その後、第３クエリ実行部２４は、図７のステップ２２２以降を再度実行する。
【００９９】
尚、第２フェーズでは、第２クエリ実行部２３が図７のステップ２２２以降を実行するものとして説明したが、第３フェーズでは、第３クエリ実行部２４が図７のステップ２２２以降を実行する。また、第３フェーズでは、図７のステップ２３０の判定は必ず「ＮＯ」となる。クエリを実行しているトランザクションが、第２フェーズでインフライトデータを生成しておりコミットされたと判定されたにも関わらず、第３フェーズで再びインフライトデータを生成しておりコミットされていないと判定されることはあり得ないからである。
【０１００】
一方、キー記憶部２５にキーが記憶されていないと判定すれば、第３クエリ実行部２４は、処理の終了をクエリ結果出力部２７に通知する（ステップ２４３）。これにより、クエリ結果出力部２７は、これまでにクエリ結果記憶部２６に記憶されたクエリ結果を外部に出力する。
【０１０１】
［本実施の形態の効果］
このように、本実施の形態では、インフライトデータ、コミット済みデータ、クエリ実行中にコミット済みデータとして保存されたデータをこの順に対象としてクエリを実行するようにした。これにより、例えばＭｏｎｇｏＤＢにトランザクション機能を追加した場合でも、提供されるクエリ機能をトランザクショナルに実現することが可能になる。
【０１０２】
具体的には、第一に、ＮｏＳＱＬデータベースに対するトランザクション機能の要求を満たすことが可能になる。即ち、アプリケーション開発の効率化のためにはトランザクション機能が必要であるが、本実施の形態によれば、既存アプリケーションのクエリを利用しながらトランザクション機能を実現できる。また、ＡＣＩＤトランザクションが必要ならばＭｏｎｇｏＤＢは使うべきではないとする考え方があるが、本実施の形態によれば、この考え方を覆すことができる。
【０１０３】
第二に、ＭｏｎｇｏＤＢの全てのクエリオペレータを実装することが可能になる。このようなクエリオペレータとしては、＄ｇｔ、＄ｇｔｅ、＄ｉｎ、＄ｌｔ、＄ｌｔｅ、＄ｎｅ、＄ｎｉｎ、＄ｏｒ、＄ａｎｄ、＄ｎｏｔ、＄ｎｏｒ、＄ｅｘｉｓｔｓ、＄ｔｙｐｅ、＄ｍｏｄ、＄ｒｅｇｅｘ、＄ｗｈｅｒｅ、＄ｇｅｏＷｉｔｈｉｎ、＄ｇｅｏＩｎｔｅｒｓｅｃｔｓ、＄ｎｅａｒ、＄ｎｅａｒＳｐｈｅｒｅ、＄ａｌｌ、＄ｅｌｅｍＭａｔｃｈ、＄ｓｉｚｅ、＄ｓｌｉｃｅ等がある。
【０１０４】
第三に、コミット済みデータのみに対してクエリを実行する場合のレイテンシと比較して１１％以下の性能劣化で、一貫性のあるクエリ結果を取得することができる。
【０１０５】
また、本実施の形態は、アイソレーションレベルとしてＲＥＡＤ  ＣＯＭＭＩＴＴＥＤレベルを提供し、かつ、その時点での最新データを照会することを可能とするものでもある。
【０１０６】
［本実施の形態におけるデータベース装置のハードウェア構成］
図９は、本実施の形態におけるデータベース装置１０のハードウェア構成例を示した図である。図示するように、データベース装置１０は、演算手段であるＣＰＵ（Central Processing Unit）１０ａと、Ｍ／Ｂ（マザーボード）チップセット１０ｂを介してＣＰＵ１０ａに接続されたメインメモリ１０ｃと、同じくＭ／Ｂチップセット１０ｂを介してＣＰＵ１０ａに接続された表示機構１０ｄとを備える。また、Ｍ／Ｂチップセット１０ｂには、ブリッジ回路１０ｅを介して、ネットワークインターフェイス１０ｆと、磁気ディスク装置（ＨＤＤ）１０ｇと、音声機構１０ｈと、キーボード／マウス１０ｉと、光学ドライブ１０ｊとが接続されている。
【０１０７】
尚、図９において、各構成要素は、バスを介して接続される。例えば、ＣＰＵ１０ａとＭ／Ｂチップセット１０ｂの間や、Ｍ／Ｂチップセット１０ｂとメインメモリ１０ｃの間は、ＣＰＵバスを介して接続される。また、Ｍ／Ｂチップセット１０ｂと表示機構１０ｄとの間は、ＡＧＰ（Accelerated Graphics Port）を介して接続されてもよいが、表示機構１０ｄがＰＣＩ Ｅｘｐｒｅｓｓ対応のビデオカードを含む場合、Ｍ／Ｂチップセット１０ｂとこのビデオカードの間は、ＰＣＩ Ｅｘｐｒｅｓｓ（ＰＣＩｅ）バスを介して接続される。また、ブリッジ回路１０ｅと接続する場合、ネットワークインターフェイス１０ｆについては、例えば、ＰＣＩ Ｅｘｐｒｅｓｓを用いることができる。また、磁気ディスク装置１０ｇについては、例えば、シリアルＡＴＡ（AT Attachment）、パラレル転送のＡＴＡ、ＰＣＩ（Peripheral Components Interconnect）を用いることができる。更に、キーボード／マウス１０ｉ、及び、光学ドライブ１０ｊについては、ＵＳＢ（Universal Serial Bus）を用いることができる。
【０１０８】
ここで、本発明は、全てハードウェアで実現してもよいし、全てソフトウェアで実現してもよい。また、ハードウェア及びソフトウェアの両方により実現することも可能である。また、本発明は、コンピュータ、データ処理システム、コンピュータプログラムとして実現することができる。このコンピュータプログラムは、コンピュータにより読取り可能な媒体に記憶され、提供され得る。ここで、媒体としては、電子的、磁気的、光学的、電磁的、赤外線又は半導体システム（装置又は機器）、或いは、伝搬媒体が考えられる。また、コンピュータにより読取り可能な媒体としては、半導体、ソリッドステート記憶装置、磁気テープ、取り外し可能なコンピュータディスケット、ランダムアクセスメモリ（ＲＡＭ）、リードオンリーメモリ（ＲＯＭ）、リジッド磁気ディスク、及び光ディスクが例示される。現時点における光ディスクの例には、コンパクトディスク−リードオンリーメモリ（ＣＤ−ＲＯＭ）、コンパクトディスク−リード／ライト（ＣＤ−Ｒ／Ｗ）及びＤＶＤが含まれる。
【０１０９】
以上、本発明を実施の形態を用いて説明したが、本発明の技術的範囲は上記実施の形態には限定されない。本発明の精神及び範囲から逸脱することなく様々に変更したり代替態様を採用したりすることが可能なことは、当業者に明らかである。
【符号の説明】
【０１１０】
１０…データベース装置、２０…クエリ処理部、２１…クエリ受付部、２２…第１クエリ実行部、２３…第２クエリ実行部、２４…第３クエリ実行部、２５…キー記憶部、２６…クエリ結果記憶部、２７…クエリ結果出力部、３０…データベース部、３１…データ記憶部、３２…トランザクション状態記憶部
【図１】
0005967628.tif 000002
【図２】
0005967628.tif 000003
【図３】
0005967628.tif 000004
【図４】
0005967628.tif 000005
【図５】
0005967628.tif 000006
【図６】
0005967628.tif 000007
【図７】
0005967628.tif 000008
【図８】
0005967628.tif 000009
【図９】
0005967628.tif 000010