適用対象:SQL Server on Linux
この記事では、SQL Server on Linux の仮想デバイス インターフェイス (VDI) クライアント SDK によって提供されるインターフェイスについて説明します。
Note
Linux 上の SQL Server 2022 (16.x) では、代わりに Transact-SQL スナップショット Backupを作成できます。
独立系ソフトウェア ベンダー (ISV) は、仮想バックアップ デバイス アプリケーション プログラミング インターフェイス (API) を使用して、自社の製品に SQL Server を統合することができます。 全般的に、Linux 上の VDI は Windows 上の VDI と同様に動作しますが、次の点が変更されます。
- Windows 共有メモリが POSIX 共有メモリになります。
- Windows セマフォが POSIX セマフォになります。
-
HRESULTやDWORDなどの Windows TYPEは、同等の整数に変更されます。 - COM インターフェイスは削除され、C++ クラスのペアに置き換えられます。
- SQL Server on Linux では名前付きインスタンスがサポートされていないため、インスタンス名への参照は削除されました。
- 共有ライブラリは、
libsqlvdi.soに実装され、/opt/mssql/lib/libsqlvdi.soにインストールされます。
この記事は、Windows 上の SQL Server VDI 仕様の詳細を示す仮想デバイス インターフェイス (VDI) リファレンスの補遺です。
また、SQL Server サンプルの GitHub リポジトリで、サンプルの VDI バックアップ ソリューションを参照してください。
ユーザーのアクセス許可のセットアップ
Linux では、POSIX プリミティブは、それを作成したユーザーとその既定のグループによって所有されます。 SQL Server によって作成されたオブジェクトの場合、既定では mssql ユーザーとmssql グループによって所有されます。 SQL Server と VDI クライアントの間の共有を許可するには、次の 2 つの方法のいずれかを使用することをお勧めします。
mssqlユーザーとして VDI クライアントを実行します。mssqlユーザーに切り替えるには、次のコマンドを実行します。sudo su mssqlmssqlユーザーをvdiuserグループに追加し、vdiuserユーザーをmssqlグループに追加します。次のコマンドを実行します。
sudo useradd vdiuser sudo usermod -a -G mssql vdiuser sudo usermod -a -G vdiuser mssqlサーバーを再起動して、SQL Server と
vdiuserの新しいグループを取得します。
クライアント関数
このセクションでは、各クライアント FUNCTION について説明します。 説明には次の情報が含まれます。
- 関数の目的
- 関数の構文
- パラメーター リスト
- 戻り値
- 解説
ClientVirtualDeviceSet::Create
パーパス
この FUNCTION は、仮想デバイス セットを作成するために使用されます。
構文
int ClientVirtualDeviceSet::Create (
char * name, // name for the set
VDConfig * cfg // configuration for the set
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| name | これにより、仮想デバイス セットが識別されます。
CreateFileMapping() によって使用される名前のルールに従う必要があります。 バックスラッシュ (\) 以外の任意の文字を使用できます。 これは文字列です。 この文字列には、ユーザーの製品名または会社名とデータベース名をプレフィックスとして付けることをお勧めします。 |
|
| cfg | これは、仮想デバイス セットの構成です。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 関数が正常に実行されました。 | |
| VD_E_NOTSUPPORTED | 構成の 1 つ以上のフィールドが無効であるか、サポートされていません。 | |
| VD_E_PROTOCOL | 仮想デバイス セットが既に存在しています。 |
解説
Create メソッドは、BACKUP または RESTORE 操作ごとに 1 回だけ呼び出す必要があります。
Close メソッドを呼び出した後、クライアントでは、インターフェイスを再利用して別の仮想デバイス セットを作成できます。
ClientVirtualDeviceSet::GetConfiguration
パーパス
この関数は、サーバーによって仮想デバイス セットが構成されるのを待機するために使用されます。
構文
int ClientVirtualDeviceSet::GetConfiguration (
time_t timeout, // in milliseconds
VDConfig * cfg // selected configuration
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| timeout | これはミリ秒単位のタイムアウト値です。 タイムアウトが発生しないようにするには、INFINITE または負の整数を使用します。 |
|
| cfg | 正常に実行されると、サーバーによって選択された構成がこの引数に格納されます。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 構成が返されました。 | |
| VD_E_ABORT |
SignalAbort が呼び出されました。 |
|
| VD_E_TIMEOUT | 関数がタイムアウトしました。 |
解説
この関数は、Alertable 状態でブロックします。 呼び出しが正常に終了すると、仮想デバイス セット内のデバイスを開くことができます。
ClientVirtualDeviceSet::OpenDevice
パーパス
この関数は、仮想デバイス セット内のいずれかのデバイスを開くために使用されます。
構文
int ClientVirtualDeviceSet::OpenDevice (
char * name, // name for the set
ClientVirtualDevice ** ppVirtualDevice // returns interface to device
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| name | これにより、仮想デバイス セットが識別されます。 | |
| ppVirtualDevice | 関数が成功した場合、仮想デバイスへのポインターが返されます。 このデバイスは GetCommand と CompleteCommand に使用されます。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 関数が正常に実行されました。 | |
| VD_E_ABORT | 中止が要求されました。 | |
| VD_E_OPEN | すべてのデバイスが開いています。 | |
| VD_E_PROTOCOL | セットが初期化中の状態ではないか、この特定のデバイスが既に開いています。 | |
| VD_E_INVALID | デバイス名が無効です。 これは、セットの構成要素として認識されている名前の 1 つではありません。 |
解説
VD_E_OPEN は、問題なく返される可能性があります。 クライアントでは、このコードが返されるまで、ループを使って OpenDevice を呼び出すことができます。
複数のデバイス (たとえば、n 個デバイス) が構成されている場合は、仮想デバイス セットから一意のデバイス インターフェイスが n 個返されます。
GetConfiguration 関数は、デバイスが開けるようになるまで待機するために使用できます。
この関数が成功しなかった場合は、ppVirtualDevice によって null 値が返されます。
ClientVirtualDevice::GetCommand
パーパス
この関数は、デバイスのキューに登録されている次のコマンドを取得するために使用されます。 要求された場合、この関数は次のコマンドを待機します。
構文
int ClientVirtualDevice::GetCommand (
time_t timeout, // time-out in milliseconds
VDC_Command** ppCmd // returns the next command
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| timeout | これは、ミリ秒単位の待機時間です。 待機時間を指定しない場合は INFINITE を使用します。 コマンドをポーリングするには、0 を使用します。 現在使用できるコマンドがない場合は、VD_E_TIMEOUT が返されます。 タイムアウトが発生した場合は、クライアントによって次のアクションが決定されます。 |
|
| タイムアウト | これは、ミリ秒単位の待機時間です。 無期限に待機するには、INFINITE または負の値を使用します。 コマンドをポーリングするには、0 を使用します。 タイムアウトするまでにいずれのコマンドも使用可能にならなかった場合は、VD_E_TIMEOUT が返されます。 タイムアウトが発生した場合は、クライアントによって次のアクションが決定されます。 |
|
| ppCmd | コマンドが正常に返された場合は、このパラメーターによって、実行するコマンドのアドレスが返されます。 返されるメモリは読み取り専用です。 コマンドが完了すると、このポインターは CompleteCommand ルーチンに渡されます。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | コマンドがフェッチされました。 | |
| VD_E_CLOSE | デバイスがサーバーによって閉じられました。 | |
| VD_E_TIMEOUT | 使用可能なコマンドがなく、タイムアウトになりました。 | |
| VD_E_ABORT | クライアントまたはサーバーが SignalAbort を使用して強制的にシャットダウンされました。 |
解説
VD_E_CLOSE が返された場合は、SQL Server によってデバイスが閉じられたことを意味します。 これは通常のシャットダウンの一部です。 すべてのデバイスが閉じられると、クライアントによって ClientVirtualDeviceSet::Close が呼び出され、仮想デバイスセットが閉じられます。
このルーチンで、コマンドを待機するためにブロックする必要がある場合、スレッドは Alertable 状態のまま維持されます。
ClientVirtualDevice::CompleteCommand
パーパス
この関数は、コマンドが終了したことを SQL Server 通知するために使用されます。 コマンドについては、適切な完了情報が返される必要があります。
構文
int ClientVirtualDevice::CompleteCommand (
VDC_Command pCmd, // the command
int completionCode, // completion code
unsigned long bytesTransferred, // bytes transferred
int64_t position // current position
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| pCmd | これは、以前に ClientVirtualDevice::GetCommand から返されたコマンドのアドレスです。 |
|
| completionCode | これは、完了状態を示す状態コードです。 このパラメーターは、すべてのコマンドについて返される必要があります。 返されるコードは、実行されるコマンドに対して適切なものである必要があります。
ERROR_SUCCESS は、コマンドが正常に実行されたことを示すために、すべてのケースで使用されます。 使用可能なコードの完全な一覧については、ファイル vdierror.h を参照してください。 |
|
| bytesTransferred | これは、正常に転送されたバイト数です。 この値は、データ転送コマンド Read および Write 用にのみ返されます。 |
|
| position | これは、GetPosition コマンドのみを対象とした応答です。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 正常に完了しました。 | |
| VD_E_INVALID |
pCmd がアクティブなコマンドではありませんでした。 |
|
| VD_E_ABORT |
Abort が通知されました。 |
|
| VD_E_PROTOCOL | デバイスが開いていません。 |
解説
なし
ClientVirtualDeviceSet::SignalAbort
パーパス
この関数は、異常終了が発生することを通知するために使用されます。
構文
int ClientVirtualDeviceSet::SignalAbort ();
| パラメーター | 引数 | 説明 |
|---|---|---|
| なし | 適用なし |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR |
Abort の通知が正常に送信されました。 |
解説
クライアントでは、BACKUP 操作または RESTORE 操作をいつでも中止できます。 このルーチンは、すべての操作を中止する必要があることを通知するものです。 仮想デバイス セット全体の状態が、Abnormally Terminated 状態になります。 後続のコマンドは、いずれのデバイスについても返されません。 未完了のコマンドはすべて自動的に完了し、完了コードとして ERROR_OPERATION_ABORTED が返されます。 クライアントでは、クライアントに提供されたバッファーの未処理の使用を安全に終了した後、ClientVirtualDeviceSet::Close を呼び出す必要があります。
ClientVirtualDeviceSet::Close
パーパス
この関数は、ClientVirtualDeviceSet::Create によって作成された仮想デバイス セットを閉じます。 これにより、仮想デバイス セットに関連付けられているすべてのリソースが解放されます。
構文
int ClientVirtualDeviceSet::Close ();
| パラメーター | 引数 | 説明 |
|---|---|---|
| なし | 適用なし |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | これは、仮想デバイス セットが正常に閉じられた場合に返されます。 | |
| VD_E_PROTOCOL | 仮想デバイス セットが開かれていないため、操作は実行されませんでした。 | |
| VD_E_OPEN | デバイスがまだ開いたままでした。 |
解説
Close の呼び出しは、仮想デバイス セットによって使用されているすべてのリソースを解放する必要があるというクライアントによる宣言です。 クライアントでは、Close を呼び出す前に、データ バッファーと仮想デバイスに関連するすべてのアクティビティが終了していることを確認する必要があります。
OpenDevice によって返されたすべての仮想デバイス インターフェイスは、Close によって無効化されます。
クライアントでは、Create 呼び出しが返された後、仮想デバイス セット インターフェイスに対して Close 呼び出しを発行することが許可されます。 この呼び出しによって、後続の BACKUP または RESTORE 操作用に、新しい仮想デバイス セットが作成されます。
1 つ以上の仮想デバイスが開いたままの状態で Close が呼び出された場合は、VD_E_OPEN が返されます。 その場合、SignalAbort が内部でトリガーされ、可能であれば、適切なシャットダウンが行われます。 VDI リソースは解放されます。 クライアントは、VD_E_CLOSE を呼び出す前に、各デバイスで ClientVirtualDeviceSet::Close の指示を待つ必要があります。 仮想デバイス セットが既に Abnormally Terminated 状態になっていることがクライアントでわかっている場合は、VD_E_CLOSE から GetCommand が通知されるのを待たず、共有バッファーでのアクティビティが終了した後すぐに、ClientVirtualDeviceSet::Close を呼び出すことができます。
ClientVirtualDeviceSet::OpenInSecondary
パーパス
この関数は、仮想デバイス セットをセカンダリ クライアントで開くために使用されます。 プライマリ クライアントでは、既に Create と GetConfiguration を使用して仮想デバイス セットが設定されている必要があります。
構文
int ClientVirtualDeviceSet::OpenInSecondary (
char * setName // name of the set
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| setName | これにより、セットが識別されます。 この名前は大文字と小文字が区別されます。また、ClientVirtualDeviceSet::Create を呼び出す際にプライマリ クライアントによって使用された名前と一致する必要があります。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 関数が正常に実行されました。 | |
| VD_E_PROTOCOL | 仮想デバイス セットが作成されていないか、このクライアントで既に開かれているか、またはセカンダリ クライアントからのオープン要求を承諾する準備が仮想デバイス セットで整っていません。 | |
| VD_E_ABORT | 操作を中止しています。 |
解説 複数のプロセス モデルを使用している場合、セカンダリ クライアントの正常終了と異常終了を検出する役割は、プライマリ クライアントが担います。
ClientVirtualDeviceSet::GetBufferHandle
パーパス
アプリケーションによっては、ClientVirtualDevice::GetCommand によって返されるバッファーを操作するために、複数のプロセスが必要になる場合があります。 その場合、コマンドを受け取るプロセスでは、GetBufferHandle を使用して、バッファーを識別するプロセス独立ハンドルを取得することができます。 その後、このハンドルによって、同じ仮想デバイス セットを開いている他のプロセスと通信することができます。 その後、そのプロセスでは、ClientVirtualDeviceSet::MapBufferHandle を使用して、バッファーのアドレスが取得されます。 このアドレスは、パートナーとは異なるアドレスになる可能性があります。なぜなら、各プロセスが異なるアドレスでバッファーをマッピングしている可能性があるからです。
構文
int ClientVirtualDeviceSet::GetBufferHandle (
uint8_t* pBuffer, // in: buffer address
unsigned int* pBufferHandle // out: buffer handle
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| pBuffer | これは、Read または Write コマンドから取得されたバッファーのアドレスです。 |
|
| BufferHandle | バッファーの一意の識別子が返されます。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 関数が正常に実行されました。 | |
| VD_E_PROTOCOL | 仮想デバイス セットは現在開いていません。 | |
| VD_E_INVALID |
pBuffer は、有効なアドレスではありません。 |
解説
GetBufferHandle 関数を呼び出すプロセスでは、データ転送が完了したときに ClientVirtualDevice::CompleteCommand を呼び出す必要があります。
ClientVirtualDeviceSet::MapBufferHandle
パーパス
この関数は、他のプロセスから取得したバッファー ハンドルから有効なバッファー アドレスを取得するために使用されます。
構文
int ClientVirtualDeviceSet::MapBufferHandle (
int dwBuffer, // in: buffer handle
uint8_t** ppBuffer // out: buffer address
);
| パラメーター | 引数 | 説明 |
|---|---|---|
| dwBuffer | これは ClientVirtualDeviceSet::GetBufferHandle によって返されるハンドルです。 |
|
| ppBuffer | これは、現在のプロセスで有効なバッファーのアドレスです。 |
| 戻り値 | 引数 | 説明 |
|---|---|---|
| NOERROR | 関数が正常に実行されました。 | |
| VD_E_PROTOCOL | 仮想デバイス セットは現在開いていません。 | |
| VD_E_INVALID |
ppBuffer は無効なハンドルです。 |
解説
解説 ハンドルが正しく通信されるように注意する必要があります。 ハンドルは、1 つの仮想デバイス セットに対してローカルです。 ハンドルを共有するパートナーでは、バッファー ハンドルが、最初に取得された仮想デバイス セットのスコープ内でのみ使用されていることを確認する必要があります。