19.4 データベース・ファイル・システム(DBFS)— POSIXファイル・ロック

Oracle Database 12c リリース2 (12.2)より、データベース・ファイル・システムPOSIXのファイル・ロック機能がサポートされます。

DBFSでは、次のタイプのアプリケーションに対してファイル・ロックがサポートされます。

  • DBFSに対するフロントエンド・インタフェースとしてDBFS_CLIENTを(マウント・モードで)使用するPOSIXアプリケーション。

  • DBFSに対するインタフェースとしてPL/SQLを使用するアプリケーション。

ノート:

Oracleは、DBFSの完全なファイル・ロックのみサポートします。完全ファイル・ロックは、バイト・ゼロのオフセットからファイルの終わりまでファイル全体をロックすることを意味します。

19.4.1 アドバイザ・ロックについて

アドバイザ・ロックは、1つのプロセスのファイルをロックするファイル・ロック・メカニズムです。

ファイル・ロック・メカニズムでは、どの形式のロックも個別に強制できず、関連プロセスからのサポートが必要になります。たとえば、プロセスP1でファイルF1に対するwriteロックが設定されている場合、ロックAPIまたはオペレーティング・システムによって、他のプロセスP2によるファイルF1でのreadまたはwriteシステム・コールの実行を回避するためのアクションは一切実行されません。ファイル・ロック・メカニズムのこの動作は、他のファイル・システムの操作にも適用できます。(ファイル・ロック・メカニズムに)関連するプロセスは、ユーザー・レベルのライブラリにより適切なAPIフォームで提供されるロックまたはロック解除プロトコルに従う必要があります。ファイル・ロック・セマンティクスはPOSIX標準に従って機能することが保証されています。

19.4.2 必須ロックについて

必須ロックは、関連プロセスからサポートを取得するファイル・ロック・メカニズムです。

必須ロックは、ロックAPIを共同で使用している、または従っている関連のプロセスに依存しない強制的なロック・スキームです。たとえば、プロセスP1がファイルF1に対するwriteロックを取得し、別のプロセスP2がファイルF1に対してread/writeシステム・コール(あるいは他のファイル・システム操作)を実行しようとすると、該当のファイルはプロセスP1で排他的にロックされるため要求はブロックされます。

19.4.3 ファイル・ロックのサポート

ファイル・ロック・メカニズムを有効にすると、アプリケーションでファイルでの様々なファイル・システム操作をブロックできます。

UNIXおよびLINUXでのfcntl()lockf()、およびflock()システム・コールによって、ファイル・ロックのサポートが提供されます。これらのシステム・コールにより、アプリケーションはdbfs_client-FUSEコールバック・インタフェースを通じてファイル・ロック機能を使用できます。fcntl()が提供するファイル・ロックはPOSIXファイル・ロックとして広く知られており、flock()で提供されるファイル・ロックはBSDファイル・ロックとして知られています。POSIXおよびBSDのファイル・ロックでは、セマンティクスと動作がそれぞれ異なります。fcntl()flock()を通じて同じファイルに設定されるロックは相互に直行です。DBFSで設計および実装されているファイル・ロック機能のセマンティクスは、POSIXファイル・ロックと似ています。DBFSでは、flock()システム・コールを通じて設定されるファイル・ロックのセマンティクスは、POSIXファイル・ロック(fcntl()など)に似ており、BSDファイル・ロックとは異なります。lockf()は、ほとんどのUNIXシステムでfcntl()システム・コールを介してラッパーとして実装されるライブラリ・コールであり、POSIXファイル・ロックのセマンティクスを提供します。DBFSでは、fcntl()flock()、およびlockf()システム・コールを通じて設定されるファイル・ロックは、POSIXファイル・ロックと同種の動作とセマンティクスを提供します。

ノート:

BSDファイル・ロックのセマンティクスはサポートされていません。

19.4.4 データベース・ファイルシステムの互換性と移行要因—ファイル・ロック

データベース・ファイルシステムのファイル・ロック機能は、RDBMSとのDBFSおよびSFSストア・プロバイダの互換性に影響しません。

DBFS_CLIENTはスタンドアロンのOCIクライアントで、OCIコールとDBMS_FUSE APIを使用します。

ノート:

この機能はOraSDK/RSFと互換します。

19.4.5 データベース・ファイル・システム・ファイル・ロックの例

これらの例では、アドバイザ・ロックと、UNIXベースのシステムで使用可能なロック機能について説明します。

次の例では、2つの実行中のプロセス、プロセスAとプロセスBを使用します。

例19-2 ロックなし

プロセスAで次のファイルが開きます。

file_desc = open(“/path/to/file”, O_RDONLY); 
/* Reads data into bufffers */ 
read(fd, buf1, sizeof(buf)); 
read(fd, buf2, sizeof(buf));
close(file_desc);

OSスケジュールに従って、プロセスBはいつでも開始でき、ファイル・データの整合性に影響を与えるwriteシステム・コールを実行できます。

例19-3 アドバイザリ・ロックは使用されているがプロセスBはプロトコルに従っていない

プロセスAで次のファイルが開きます。

file_desc = open(“/path/to/file”, O_RDONLY); 
ret = AcquireLock(file_desc, RD_LOCK); 
if(ret) 
{ 
	read(fd, buf1, sizeof(buf)); 
	read(fd, buf2, sizeof(buf)); 
	ReleaseLock(file_desc); 
} 
close(file_desc);

OSスケジュールに従って、プロセスBはいつでも開始でき、プロセスAがすでにreadロックを保持していることを無視してwriteシステム・コールも実行できます。

プロセスBで次のファイルが開きます。

file_desc1 = open(“/path/to/file”, O_WRONLY); 
write(file_desc1, buf, sizeof(buf)); 
close(file_desc1);

前述のコードが実行されると、ファイルでデータの不整合が生じます。

例19-4 アドバイザリ・ロックの使用とプロトコルに従うプロセス

プロセスAで次のファイルが開きます。

file_desc = open(“/path/to/file”, O_RDONLY); 
ret = AcquireLock(file_desc, RD_LOCK); 
if(ret) 
{
	read(fd, buf1, sizeof(buf)); 
	read(fd, buf2, sizeof(buf)); 
	ReleaseLock(file_desc);
}
close(file_desc);

プロセスBで次のファイルが開きます。

file_desc1 = open(“/path/to/file”, O_WRONLY); 
ret = AcquireLock(file_desc1, WR_LOCK); 
/* The above call will take care of checking the existence of a lock */ 
if(ret) 
{ 
	write(file_desc1, buf, sizeof(buf)); 
	ReleaseLock(file_desc1); 
} close(file_desc1);

プロセスBはロックAPIに従います。このAPIによってプロセスはロックを取得せずにファイルにwriteを実行することはありません。

19.4.6 DBFSロックの動作

この項では、DBFSロックの動作について説明します。

The DBFSファイル・ロック機能により、次の動作が行われます。

  • DBFSのファイル・ロックが冪等機能で実装されます。1つのプロセスで同じファイルに対して"N"回readまたはwriteロック・コールが実行された場合、1回目のコールのみ有効で、以降の"N-1"回のコールは冗長として処理され、No Operation (NOOP)が返されます。

  • ファイルは1回だけロック解除できます。1つのプロセスで同じファイルに対して"N"回unlockコールが実行された場合、1回目のコールのみ有効で、以降の"N-1"回のコールは冗長として処理され、NOOPが返されます。

  • readからwriteへのロック変換のみサポートされます。1つのプロセスPでファイルFreadロックが設定されている場合(またPreadロックを保持する唯一のプロセスである場合)、ファイルFでのPによるwriteロック要求によって、readロックはexclusive/writeロックに変換されます。

19.4.7 ファイル・ロックのスケジュール設定

DBFSファイル・ロック機能はロックのスケジュール設定をサポートします。

この機能はDBFSクライアント側にのみ実装されます。ロック要求スケジュール設定は、クライアント・アプリケーションがそのfcntl()lockf()、およびflock()コールでブロッキング・コール・セマンティクスを使用している場合に必要です。

次の2種類のスケジュール設定があります。

Oracleは、スケジュール動作の切り替えに関して次のコマンド・ライン・オプションを提供しています。

Mount -o lock_sched_option = lock_sched_option Value;

表19-1 lock_sched_option値の説明

説明
1 スケジュールのタイプをグリーディ・スケジュールに設定します。(デフォルト)
2 スケジュールのタイプをフェア・スケジュールに設定します。

ノート:

ロック要求のスケジュール設定は、DBFS_CLIENTマウント単位でのみ機能します。たとえば、ロック要求は同じファイル・システムの複数のマウントでスケジュール設定されません。

19.4.7.1 グリーディ・スケジュール

このスケジュール手法では、ファイル・ロック要求は保証された順序に従いません。

ノート:

これは、DBFS_CLIENTで提供されるデフォルトのスケジュール・オプションです。

ファイルFがプロセスP1readロックされている場合、およびプロセスP2P3がファイルFでのブロックwriteロック要求をサブミットする場合、プロセスP2P3は(スピン・ロックの形式を使用して)ブロックされ、ロックを取得するまで順番に待機します。待機中、プロセスP4がファイルFreadロック要求(ブロック・コールまたは非ブロック・コール)を送信すると、writeロックの取得を待機しているプロセスが2つ(P2P3)ある場合でも、P4readロックが付与されます。P1P4の両方がそれぞれのreadロックを解除すると、P2およびP3のいずれがロックを取得できます。ただし、プロセスP2P3がロックを取得する順序は決定されません。プロセスP2が最初に要求しても、プロセスP3の要求がロック解除されてロックを取得し、プロセスP2P3がロックを解除するまで待機する必要がある場合もあります。

19.4.7.2 フェア・スケジュール

フェア・スケジュール設定手法は、ファイルごとにキューイング・メカニズムを使用して実装されます。

たとえば、ファイルFがプロセスP1で読取りロックされ、プロセスP2P3がファイルFでのブロック書込みロック要求を送信した場合、これら2つのプロセスは(スピン・ロックの形式を使用して)ブロックされ、ロックの取得を待機します。要求はDBFSクライアントで受信された順序でキューイングされます。プロセスP4がファイルFに対する読取りロック要求(ブロック・コールまたは非ブロック・コール)を送信すると、このプロセスに対して読取りロックが付与できる場合でもこの要求はキューイングされます。

DBFSクライアントによって、P1がその読取りロックを解放した後、ロック要求が受け付けられる順序はP2->P3 -> P4になります。

つまり、P2が最初にロックを取得します。P2がそのロックを解除した後に、P3がロックを取得し、その後は同様に続いていきます。